Numpy 切片中的视图和副本

Numpy 切片中的视图和副本

在使用Numpy进行数据处理时,我们通常需要使用数组的切片进行操作。这时候需要注意,切片操作可能会得到数组的视图或副本。本文将深入探讨切片中的视图和副本的概念和区别,并通过实例进行说明。

阅读更多:Numpy 教程

视图和副本

在Numpy中,视图和副本都是数组的一部分或整体的引用,在进行切片操作时,得到视图和副本的判断基于以下三个因素:

  1. 切片是否由单个整数或布尔值组成;
  2. 切片是否包含任何”:”,即为切片;
  3. 切片是否包含未排序索引或重复索引;

以上三个因素都成立,即可视为切片得到数组的视图;否则,则是副本。

需要注意的是,得到视图或副本不仅影响数据的处理和传递,还会影响到计算性能和显存使用效率。

实例说明

我们使用numpy数组ar作为例子,当ar数据类型为整数时,其所占用的显存为8字节。我们通过以下实例来说明对数组进行切片得到视图还是副本。

视图实例

import numpy as np

ar = np.array([1, 2, 3, 4, 5, 6])
ar_slice = ar[3:]

print(f"ar_slice: {ar_slice}")
print(f"Is ar_slice a view? {ar.flags['OWNDATA']}")

此时,我们使用ar[3:]切片得到了ar中的一部分,即ar_slice。运行结果如下:

ar_slice: [4 5 6]
Is ar_slice a view? True

当我们检查ar_slice是否为视图时,可以发现其为视图。

接下来,我们再对实例进行拓展。此时,我们使用ar1作为数据源,两次用切片对其产生ar2和ar3数组。

ar1 = np.array([1, 2, 3, 4, 5, 6])
ar2 = ar1[1:4]
ar3 = ar2[1:]

print(f"ar2: {ar2}, Is ar2 a view? {ar2.flags['OWNDATA']}")
print(f"ar3: {ar3}, Is ar3 a view? {ar3.flags['OWNDATA']}")

此时,我们得到了两个数组ar2和ar3,运行结果如下:

ar2: [2, 3, 4], Is ar2 a view? True
ar3: [3, 4], Is ar3 a view? True

由此可以得出,ar2为ar1的视图,而ar3则是ar2的视图。

副本实例

接着,我们将布尔数组作为切片索引,得到ar4数组,同时检查其是否为视图。

ar4 = ar[ar > 3]

print(f"ar4: {ar4}, Is ar4 a view? {ar4.flags['OWNDATA']}")

此时,我们得到了ar4数组,运行结果如下:

ar4: [4 5 6]
Is ar4 a view? False

我们可以发现,得到的ar4数组是ar的副本,由于需要建立新的整数数组,因此占用的显存相比ar1数组增加了4个字节。

反转视图为副本

接下来,我们再使用ar_array作为数据源,通过ar_array[::-1]切片对数组进行反转,观察其结果。

ar5 = ar[::-1]

print(f"ar5: {ar5}")
print(f"Is ar5 a view? {ar5.flags['OWNDATA']}")

此时,我们得到了ar5数组,运行结果如下:

ar5: [6 5 4 3 2 1]
Is ar5 a view? False

由于切片涉及到反转,因此得到的ar5是一个新的副本数组。

总结

在使用Numpy进行数据处理时,我们需要注意切片操作得到的数组是视图还是副本。视图的产生可以提高计算性能和显存使用效率,而副本则需要占用更多的显存空间。在判断是否为视图或副本时,需要注意判断切片的类型和切片中是否包含未排序或重复索引。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程