假设我有以下内容numpy.array
:
In[]: x
Out[]:
array([[1, 2, 3, 4, 5],
[5, 2, 4, 1, 5],
[6, 7, 2, 5, 1]], dtype=int16)
In[]: y
Out[]:
array([[-3, -4],
[-4, -1]], dtype=int16)
Run Code Online (Sandbox Code Playgroud)
我想替换x
by的子数组y
并尝试了以下操作:
In[]: x[[0,2]][:,[1,3]]= y
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望这种情况发生:
In[]: x
Out[]:
array([[1, -3, 3, -4, 5],
[5, 2, 4, 1, 5],
[6, -4, 2, -1, 1]], dtype=int16)
Run Code Online (Sandbox Code Playgroud)
赋值行没有给我任何错误,但是当我检查输出时x
In[]: x
Run Code Online (Sandbox Code Playgroud)
我发现这x
没有改变,即作业没有发生。
我怎样才能完成这项任务?为什么任务没有完成?
“花式索引”x[[0,2]][:,[1,3]]
返回数据的副本。使用切片建立索引会返回一个视图。分配确实发生了,但是分配给了 的副本(实际上是...的副本的副本)x
。
在这里我们看到索引返回一个副本:
>>> x[[0,2]]
array([[1, 2, 3, 4, 5],
[6, 7, 2, 5, 1]], dtype=int16)
>>> x[[0,2]].base is x
False
>>> x[[0,2]][:, [1, 3]].base is x
False
>>>
Run Code Online (Sandbox Code Playgroud)
现在您可以使用花式索引来设置数组值,但在嵌套索引时则不能。
您可以使用np.ix_
来生成索引并执行分配:
>>> x[np.ix_([0, 2], [1, 3])]
array([[2, 4],
[7, 5]], dtype=int16)
>>> np.ix_([0, 2], [1, 3])
(array([[0],
[2]]), array([[1, 3]]))
>>> x[np.ix_([0, 2], [1, 3])] = y
>>> x
array([[ 1, -3, 3, -4, 5],
[ 5, 2, 4, 1, 5],
[ 6, -4, 2, -1, 1]], dtype=int16)
>>>
Run Code Online (Sandbox Code Playgroud)
您还可以使其与广播的花哨索引一起使用(如果这甚至是术语),但它并不漂亮
>>> x[[0, 2], np.array([1, 3])[..., None]] = y
>>> x
array([[ 1, -3, 3, -4, 5],
[ 5, 2, 4, 1, 5],
[ 6, -4, 2, -1, 1]], dtype=int16)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,目前 NumPy 讨论邮件列表上有一些关于更好地支持“正交”索引的有趣讨论,因此将来这可能会变得更容易。