如何使用嵌套索引为数组元素赋值?

时间:2017-04-27 19:47:49

标签: python numpy

import numpy as np

data = np.zeros((5,3))

In [44]: data   
Out[44]:    
array([[ 0.,  0.,  0.],
   [ 0.,  0.,  0.],
   [ 0.,  0.,  0.],
   [ 0.,  0.,  0.],
   [ 0.,  0.,  0.]])

In [45]: data[[0,1,2]] = 2

In [46]: data   
Out[46]:    
array([[ 2.,  2.,  2.],
   [ 2.,  2.,  2.],
   [ 2.,  2.,  2.],
   [ 0.,  0.,  0.],
   [ 0.,  0.,  0.]])

In [47]: data[[0,1,2]][2]   
Out[47]: array([ 2.,  2.,  2.])

In [48]: data[[0,1,2]][2] = 3   

In [49]: data[[0,1,2]][2]   
Out[49]: array([ 2.,  2.,  2.])

我期待最后的结果是[3.,3.,3。]。为什么用双指数替换元素是不行的?有没有办法使用双索引更改数组的元素?

3 个答案:

答案 0 :(得分:2)

data[[0,1,2]][2] = 3  

data[[0,1,2]]data的一部分副本,而不是view的副本。表达式正在修改该副本,而不是data本身。

In [298]: data=np.arange(15).reshape(5,3)
In [299]: data[[0,1,2]]
Out[299]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
In [300]: data[[0,1,2]][2]
Out[300]: array([6, 7, 8])

此作业有效:

data[[0,1,2]] = 2

因为'高级索引'就在=之前。在第一种情况下,它被另一个索引层分开。

答案 1 :(得分:2)

Python评估data[i][j] = x的方式是首先评估tmp = data.__getitem__(i),然后在该临时对象上调用tmp.__setitem__(j, x)。在numpy的情况下,当您使用列表对数组进行索引来评估data[[1,2,3]]时,您将创建一个新数组,其中包含这些位置的数据副本。我们无法在data上创建视图,因为列表可能包含分散的索引,甚至是重复的索引。因此tmp对象未连接到原始data对象。分配tmp[2] = 3发生了,但随后tmp被丢弃。

答案 2 :(得分:0)

这很奇怪。它必须与numpy.array的结构相关。从我对numpy的经验来看,数组切片是用数据[outerindex,innerindex]而不是传统的Python列表数据[outerindex] [innerindex]完成的。

如果你这样做

data[[0,1,2],2] = 3 

您可以按照预期修改数据:

>>>data
array([ 2., 2., 3.],
      [ 2., 2., 3.],
      [ 2., 2., 3.],
      [ 0., 0., 0.],
      [ 0., 0., 0.])