副本与视图
numpy中对数组运算或者操作时,返回结果是数组的副本或视图
副本
副本一般发生在:
2.调用np.ndarray.copy()
视图
视图一般发生在:
1.numpy的切片操作,返回的是原始数据的视图;
2.调用np.ndarray.view()
视图与副本对比
在numpy中操作视图可以改变原始数据的值,但不会改变原始数据的shape;而操作副本不会改变原始数据的值。
numpy的视图、副本与python的浅拷贝、深拷贝
视图可以看成是浅拷贝,副本可以看成是深拷贝。但又与python的浅拷贝、深拷贝有区别。
python中,对象赋值实际上是对对象的引用。创建一个对象a后,把a赋值给另一个变量b,这里python并没有拷贝这个对象,而只是拷贝了这个对象的引用,因此称之为浅拷贝,id(a)==id(b)返回True。list.append()函数操作的也是引用。eg:
b=1
a=[]
a.append(b)#a=[1]
id(a[0])==id(b)#True
此时操作变量b会对a列表有影响,操作a[0]也会对变量b有影响。为了防止误操作,应用深拷贝。
import copy
b=1
a=[]
a.append(copy.deepcopy(b))#a=[1]
id(a[0])==id(b)#False
赋值运算是原数组,np.ndarray.copy()创建副本。对副本进行操作时,不会影响原始数据,因为它们的物理内存不在同一位置。
x=np.array([1,2,3,4])
y=x
y[-1]=-1#x和y都变成[1,2,3,-1]
y=x.copy()
print(x)#[1,2,3,-1]
print(y)#[1,2,3,4]
这里回到这块的主题,python中的浅拷贝对应到numpy的视图,但不完全相同,因为python的浅拷贝id是相同的,numpy的视图则是不同的:
import numpy as np
a=np.array([1,2,3,4])
b=a.view()
id(a)==id(b)#False
numpy的切片
numpy对数据操作更灵活,eg:
x = np.array(
[[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25],
[26, 27, 28, 29, 30],
[31, 32, 33, 34, 35]])
x[::2,:3:2]=-1
print(x)
[[-1 12 -1 14 15]
[16 17 18 19 20]
[-1 22 -1 24 25]
[26 27 28 29 30]
[-1 32 -1 34 35]
x.shape是5*5,可以看到这里6个数字变成了-1,首先从第一个维度是,选中所有索引(行),步长为2,那么选中的就是0,2,4;第二个维度是,先选中起始到索引值为2的索引(列),步长为2,那么选中的就是0,2。因此,改变的值的位置为x[0][0],x[0][2],x[2][0],x[2][2],x[4][0],x[4][2]
reference
1.https://github.com/datawhalechina/team-learning-program/blob/master/IntroductionToNumpy/task02%20%E7%B4%A2%E5%BC%95/05.%20%E7%B4%A2%E5%BC%95%E3%80%81%E5%88%87%E7%89%87%E4%B8%8E%E8%BF%AD%E4%BB%A3.ipynb
2.https://www.runoob.com/numpy/numpy-copies-and-views.html
3.https://blog.csdn.net/u010099495/article/details/50276833