numpy 数组复制与广播机制

一、视图和复制

1. 完全不复制

下面的结果,是因为数组是一个可变的对象:

>>> a = np.arange(12)
>>> b = a            # 不会创建新的数组对象,而是多了一个引用
>>> b is a           # a和b只是同一个数组的两个名字
True
>>> b.shape = 3,4    # 会同时修改a的形状
>>> a.shape
(3, 4)

2. view视图

不同的数组对象可以共享同样的数据。view方法就可以实现这一操作:

>>> c = a.view()   # 现在开始c是一个新的数组,并且和a共享数据
>>> c is a      # 说明c和a是两个不同的对象
False
>>> c.base is a                        # c是a数组的数据视图
True
>>> c.flags.owndata     # 可以看到c没有自己的数据
False
>>>
>>> c.shape = 2,6                      # a的形状不会发生改变
>>> a.shape
(3, 4)
>>> c[0,4] = 1234                      # 但是a的数据会跟着发生改变
>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])

理解view,只需要注意两者共享数据,此外其它所有都是独立的。

切片操作,则会返回一个数组的view视图:

>>> s = a[ : , 1:3]     
>>> s[:] = 10           # s[:]是s的一个视图。注意与s=10区分开,不要混淆。
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

3. 深度拷贝

copy方法生成数组的一个完整的拷贝,包括其数据。

>>> d = a.copy()                         
>>> d is a
False
>>> d.base is a                     
False
>>> d[0,0] = 9999
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])

二、广播机制

广播允许通用函数以有意义的方式处理异构的输入。也就是让形状不一样的数组在进行运算的时候,能够得到合理的结果。其规则如下:

  1. 如果所有输入数组的维数都不相同,则会重复在较小数组的形状前面加上“1”,直到所有数组的维数都相同。
  2. 确保沿特定维度的大小为1的数组的大小与沿该维度的最大形状的数组的大小相同。假定数组元素的值在“广播”数组的该维度上相同。

应用广播规则后,所有数组的大小将会匹配。请看下面的例子,加深理解:

>>> a=np.array([[0,0,0], [10,10,10],[20,20,20],[30]*3])
>>> a
array([[ 0,  0,  0],
       [10, 10, 10],
       [20, 20, 20],
       [30, 30, 30]])
>>> b = np.array([0,1,2])
>>> b
array([0, 1, 2])
>>> a + b
array([[ 0,  1,  2],
       [10, 11, 12],
       [20, 21, 22],
       [30, 31, 32]])
>>> c= np.array([[1],[2],[3],[4]])
>>> c
array([[1],
       [2],
       [3],
       [4]])
>>> a + c
array([[ 1,  1,  1],
       [12, 12, 12],
       [23, 23, 23],
       [34, 34, 34]])

原文地址:https://www.cnblogs.com/lavender1221/p/12641195.html