ias*_*nas 88 python arrays numpy in-place variable-assignment
我最近应用这个解决方案来平均每N行矩阵.虽然解决方案通常起作用,但在应用于7x1阵列时遇到了问题.我注意到问题是在使用-=运算符时.举一个小例子:
import numpy as np
a = np.array([1,2,3])
b = np.copy(a)
a[1:] -= a[:-1]
b[1:] = b[1:] - b[:-1]
print a
print b
Run Code Online (Sandbox Code Playgroud)
哪个输出:
[1 1 2]
[1 1 1]
Run Code Online (Sandbox Code Playgroud)
因此,在数组的情况下a -= b产生不同的结果a = a - b.直到现在我才想到这两种方式完全相同.有什么不同?
为什么我提到的用于求和矩阵中每N行的方法是如何工作的,例如7x4矩阵而不是7x1阵列?
Ale*_*ley 79
注意:在版本1.13.0以后的共享内存的NumPy阵列上使用就地操作不再是问题(请参阅此处的详细信息).这两个操作将产生相同的结果.此答案仅适用于早期版本的NumPy.
在计算中使用变异数组会导致意外结果!
在问题的例子中,减法-=修改了第二个元素,a然后立即在第三个元素的操作中使用了修改后的第二个元素a.
以下是a[1:] -= a[:-1]一步一步发生的事情:
a是带有数据的数组[1, 2, 3].
我们对这些数据有两种看法:a[1:]是[2, 3],a[:-1]是[1, 2].
就地减法-=开始.从1的第一个元素中a[:-1]减去1的第一个元素a[1:].这已被修改a为[1, 1, 3].现在我们有了a[1:]数据视图[1, 3],并且a[:-1]是数据视图[1, 1](数组的第二个元素a已经更改).
a[:-1]现在[1, 1],NumPy必须从第二个元素中减去它的第二个元素,即1(不再是2!)a[1:].这样可以a[1:]查看值[1, 2].
a现在是一个包含值的数组[1, 1, 2].
b[1:] = b[1:] - b[:-1]没有这个问题,因为首先b[1:] - b[:-1]创建一个新数组,然后将此数组中的值赋给b[1:].它不会修改b减法过程本身,所以意见b[1:],并b[:-1]没有改变.
一般建议是避免将一个视图与另一个视图重叠,如果它们重叠.这包括操作员-=,*=等,并且使用out在通用功能参数(如np.subtract和np.multiply),以写回阵列中的一个.
glg*_*lgl 43
在内部,区别在于:
a[1:] -= a[:-1]
Run Code Online (Sandbox Code Playgroud)
相当于:
a[1:] = a[1:].__isub__(a[:-1])
a.__setitem__(slice(1, None, None), a.__getitem__(slice(1, None, None)).__isub__(a.__getitem__(slice(1, None, None)))
Run Code Online (Sandbox Code Playgroud)
而这个:
b[1:] = b[1:] - b[:-1]
Run Code Online (Sandbox Code Playgroud)
映射到这个:
b[1:] = b[1:].__sub__(b[:-1])
b.__setitem__(slice(1, None, None), b.__getitem__(slice(1, None, None)).__sub__(b.__getitem__(slice(1, None, None)))
Run Code Online (Sandbox Code Playgroud)
在某些情况下,__sub__()并__isub__()以类似的方式工作.但是可变对象在使用时应该变异并返回自己__isub__(),而它们应该返回一个新对象__sub__().
在numpy对象上应用切片操作会在它们上创建视图,因此使用它们可以直接访问"原始"对象的内存.
| 归档时间: |
|
| 查看次数: |
6841 次 |
| 最近记录: |