Python 为什么替换numpy数组中的值并不总是有效

Python 为什么替换numpy数组中的值并不总是有效,python,arrays,numpy,overwrite,Python,Arrays,Numpy,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.

我尝试使用以下命令替换/覆盖数组中的值:

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 = 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.]])
因此,我有两个问题:

1-为什么第一个命令

test[np.where(test[...,0] != 0)][...,1:3] = np.array([10,11])
不允许修改阵列测试?为什么不允许访问阵列单元并覆盖它们

2-考虑到我的代码需要使用上面的命令选择单元格,我如何使其工作

非常感谢

我给你做一个。这确实有效:

为什么??它是两个因素的组合-
numpy
索引和
\uuuuuu setitem\uuuuuu
调用

python
解释器有点向后读取行。当它到达
=
时,它会尝试调用最左边的
\uuuuu setitem\uuuuuu
\uuuu setitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

现在,当我们在
numpy
中建立索引时,我们有三种基本方法可以做到这一点

  • 切片(返回视图)
  • “高级索引”(返回副本)
  • “简单索引”(还返回副本)
“高级”索引和“简单”索引之间的一个主要区别是
numpy
数组的
\uuuu setitem\uuuu
函数可以解释高级索引。而
视图
意味着数据地址是相同的,因此我们不需要
\uuuu setitem\uuuu
来访问它们

因此:

但是,由于
np.where(test[…,0]!=0)
是一个
高级索引
(test[np.where(test[…,0]!=0)])
返回一个副本,该副本将丢失,因为它从未分配过。它确实获取了我们想要的元素并将它们设置为
[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]
是一个视图,因此它仍然指向相同的内存。现在
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.\uuuuuu setitem\uuuuuuu
,这也正确地设置了数据

更简单的(也是最具Python风格的)是:

test[test[...,0] != 0, 1:3] = np.array([10,11])

测试[where…]
步骤复制一份。下面的
[…]=…
修改该副本,而不是原始副本。
视图
传递更改,但不传递副本。
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[np.where(test[...,0] != 0), 1:3] = np.array([10, 11])
test[test[...,0] != 0, 1:3] = np.array([10,11])