为什么替换 numpy 数组中的值并不总是有效
Why replacing values in numpy array does not always work
我正在尝试使用以下命令 replace/overwrite 数组中的值:
import numpy as np
test = np.array([[4,5,0],[0,0,0],[0,0,6]])
test
Out[20]:
array([[4., 5., 0.],
[0., 0., 0.],
[0., 0., 6.]])
test[np.where(test[...,0] != 0)][...,1:3] = np.array([[10,11]])
test
Out[22]:
array([[4., 5., 0.],
[0., 0., 0.],
[0., 0., 6.]])
但是,在Out22中可以看到,数组test并没有被修改。所以我得出结论,不可能简单地覆盖数组的一部分或几个单元格。
然而,在其他情况下,可以覆盖数组的几个单元格。例如,在下面的代码中:
test = np.array([[1,2,0],[0,0,0],[0,0,3]])
test
Out[11]:
array([[1., 2., 0.],
[0., 0., 0.],
[0., 0., 3.]])
test[test>0]
Out[12]:
array([1., 2., 3.])
test[test>0] = np.array([4,5,6])
test
Out[14]:
array([[4., 5., 0.],
[0., 0., 0.],
[0., 0., 6.]])
因此,我的 2 个问题:
1- 为什么第一个命令
test[np.where(test[...,0] != 0)][...,1:3] = np.array([10,11])
不允许修改数组测试?为什么它不允许访问数组单元格并覆盖它们?
2- 考虑到我的代码需要使用上面的命令 select 单元格,我怎样才能让它工作?
非常感谢!
我给你做一个。 有效:
test[...,1:3][np.where(test[...,0] != 0)] = np.array([[10,11]])
array([[ 4, 10, 11],
[ 0, 0, 0],
[ 0, 0, 6]])
为什么?它是两个因素的组合 - numpy
索引和 .__setitem__
调用。
python
解释器向后读取行。当它到达 =
时,它会尝试在最左边的事物上调用 .__setitem__
。 __setitem__
是(希望)对象的一种方法,并且有两个输入,目标和索引(在它之前 [...]
之间的任何内容)。
a[b] = c #is intepreted as
a.__setitem__(b, c)
现在,当我们在 numpy
中建立索引时,我们可以使用三种基本方法。
- 切片(returns 次观看)
- 'advanced indexing'(returns份)
- 'simple indexing'(也returns份)
“高级”和“简单”索引之间的一个主要区别是 numpy
数组的 __setitem__
函数可以解释高级索引。而 views
表示数据地址相同,所以我们不需要 __setitem__
来访问它们。
所以:
test[np.where(test[...,0] != 0)][...,1:3] = np.array([[10,11]]) #is intepreted as
(test[np.where(test[...,0] != 0)]).__setitem__( slice([...,1:3]),
np.array([[10,11]]))
但是,由于 np.where(test[...,0] != 0)
是一个 advanced index
,(test[np.where(test[...,0] != 0)])
returns 一个副本,然后丢失,因为它从未被分配。它确实获取了我们想要的元素并将它们设置为 [10,11]
,但结果丢失在缓冲区中的某个地方。
如果我们这样做:
test[..., 1:3][np.where(test[..., 0] != 0)] = np.array([[10, 11]]) #is intepreted as
(test[..., 1:3]).__setitem__( np.where(test[...,0] != 0), np.array([[10,11]]) )
test[...,1:3]
是一个view,所以还是指向同一个内存。现在 setitem
在 test[...,1:3]
中查找对应 np.where(test[...,0] != 0)
的位置,并将它们设置为等于 np.array([[10,11]])
。一切正常。
您也可以这样做:
test[np.where(test[...,0] != 0), 1:3] = np.array([10, 11])
现在,由于所有索引都在一组括号中,它会在这些索引上调用 test.__setitem__
,这也会正确设置数据。
更简单的(也是最 pythonic 的)是:
test[test[...,0] != 0, 1:3] = np.array([10,11])
我正在尝试使用以下命令 replace/overwrite 数组中的值:
import numpy as np
test = np.array([[4,5,0],[0,0,0],[0,0,6]])
test
Out[20]:
array([[4., 5., 0.],
[0., 0., 0.],
[0., 0., 6.]])
test[np.where(test[...,0] != 0)][...,1:3] = np.array([[10,11]])
test
Out[22]:
array([[4., 5., 0.],
[0., 0., 0.],
[0., 0., 6.]])
但是,在Out22中可以看到,数组test并没有被修改。所以我得出结论,不可能简单地覆盖数组的一部分或几个单元格。
然而,在其他情况下,可以覆盖数组的几个单元格。例如,在下面的代码中:
test = np.array([[1,2,0],[0,0,0],[0,0,3]])
test
Out[11]:
array([[1., 2., 0.],
[0., 0., 0.],
[0., 0., 3.]])
test[test>0]
Out[12]:
array([1., 2., 3.])
test[test>0] = np.array([4,5,6])
test
Out[14]:
array([[4., 5., 0.],
[0., 0., 0.],
[0., 0., 6.]])
因此,我的 2 个问题:
1- 为什么第一个命令
test[np.where(test[...,0] != 0)][...,1:3] = np.array([10,11])
不允许修改数组测试?为什么它不允许访问数组单元格并覆盖它们?
2- 考虑到我的代码需要使用上面的命令 select 单元格,我怎样才能让它工作?
非常感谢!
我给你做一个。 有效:
test[...,1:3][np.where(test[...,0] != 0)] = np.array([[10,11]])
array([[ 4, 10, 11],
[ 0, 0, 0],
[ 0, 0, 6]])
为什么?它是两个因素的组合 - numpy
索引和 .__setitem__
调用。
python
解释器向后读取行。当它到达 =
时,它会尝试在最左边的事物上调用 .__setitem__
。 __setitem__
是(希望)对象的一种方法,并且有两个输入,目标和索引(在它之前 [...]
之间的任何内容)。
a[b] = c #is intepreted as
a.__setitem__(b, c)
现在,当我们在 numpy
中建立索引时,我们可以使用三种基本方法。
- 切片(returns 次观看)
- 'advanced indexing'(returns份)
- 'simple indexing'(也returns份)
“高级”和“简单”索引之间的一个主要区别是 numpy
数组的 __setitem__
函数可以解释高级索引。而 views
表示数据地址相同,所以我们不需要 __setitem__
来访问它们。
所以:
test[np.where(test[...,0] != 0)][...,1:3] = np.array([[10,11]]) #is intepreted as
(test[np.where(test[...,0] != 0)]).__setitem__( slice([...,1:3]),
np.array([[10,11]]))
但是,由于 np.where(test[...,0] != 0)
是一个 advanced index
,(test[np.where(test[...,0] != 0)])
returns 一个副本,然后丢失,因为它从未被分配。它确实获取了我们想要的元素并将它们设置为 [10,11]
,但结果丢失在缓冲区中的某个地方。
如果我们这样做:
test[..., 1:3][np.where(test[..., 0] != 0)] = np.array([[10, 11]]) #is intepreted as
(test[..., 1:3]).__setitem__( np.where(test[...,0] != 0), np.array([[10,11]]) )
test[...,1:3]
是一个view,所以还是指向同一个内存。现在 setitem
在 test[...,1:3]
中查找对应 np.where(test[...,0] != 0)
的位置,并将它们设置为等于 np.array([[10,11]])
。一切正常。
您也可以这样做:
test[np.where(test[...,0] != 0), 1:3] = np.array([10, 11])
现在,由于所有索引都在一组括号中,它会在这些索引上调用 test.__setitem__
,这也会正确设置数据。
更简单的(也是最 pythonic 的)是:
test[test[...,0] != 0, 1:3] = np.array([10,11])