具有高级混合索引的Numpy子数组赋值

时间:2016-03-24 18:49:51

标签: python arrays numpy indexing

原始问题

当我尝试分配数组的某些元素时,我收到一条非常奇怪的错误消息。我正在使用切片和一组索引的组合。请参阅以下简单示例。

 import scipy as sp

 a = sp.zeros((3, 4, 5))
 b = sp.ones((4, 5))

 I = sp.array([0, 1, 3])

 b[:, I] = a[0, :, I]

此代码引发了以下ValueError

ValueError:形状不匹配:形状(3,4)的值数组无法广播到形状的索引结果(3,4)

-

跟进

使用切片和seq的组合时要小心。整数。正如github所指出的那样:

x = rand(3, 5, 7)

print(x[0, :, [0,1]].shape)
# (2, 5)

print(x[0][:, [0,1]].shape)
# (5, 2)

这是numpy的设计工作方式,但是有点令人困惑的是x [0] [:,I]与x [0,:,I]不同。由于这是我想要的行为,我选择在我的代码中使用x [0] [:,I]。

3 个答案:

答案 0 :(得分:1)

我在这里使用索引[0,1,4]收到此错误:

IndexError: index 4 is out of bounds for axis 2 with size 4

它建议将值4用作索引,而SIZE 4则表示最大索引为3。

编辑:现在您已将其更改为[0, 1, 3],此处运行正常。

编辑:使用您当前的代码,我得到相同的错误,但是当我自己打印数组时,它们具有横向形状:

print b[:, I]
print a[0, :, I]

[[ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]]

[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]

答案 1 :(得分:1)

首先,看起来你在第6行错过了一个逗号:

I = sp.array([0,1,4])

其次,我希望数组I中的值4引发一个IndexError,因为a和b的最大维度都是4.我怀疑你可能想要:

I = sp.array([0,1,3])

进行这些更改为我运行程序,我得到b:

[[ 0.  0.  1.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  1.  0.]]

我怀疑你想要的是什么。

答案 2 :(得分:1)

在将代码复制到问题时看起来有些错误。

但我怀疑索引存在已知问题:

In [73]: a=np.zeros((2,3,4)); b=np.ones((3,4)); I=np.array([0,1])

制作I 2个元素。索引b给出了预期的(3,2)形状。切片中的3行,I索引中的2列

In [74]: b[:,I].shape
Out[74]: (3, 2)

但是使用3d a我们可以获得转置。

In [75]: a[0,:,I].shape
Out[75]: (2, 3)

并且赋值会产生错误

In [76]: b[:,I]=a[0,:,I]
...
ValueError: array is not broadcastable to correct shape

首先将I定义的2元素维度放置,然后将{3}元素定义为:秒。这是前面已经讨论过的混合高级索引的情况 - 并且还存在一个bug问题。 (我必须看看那些)。

您可能正在使用较新的numpy(或scipy)并收到其他错误消息。

据记载,使用两个数组或列表进行索引,并在中间切片,将切片放在最后,例如。

In [86]: a[[[0],[0],[1],[1]],:,[0,1]].shape
Out[86]: (4, 2, 3)

a[0,:,[0,1]]也发生了同样的事情。但是有一个很好的论据,它不应该是这样的。

关于修复,您可以转置一个值,或更改索引

In [88]: b[:,I]=a[0:1,:,I]

In [90]: b[:,I]=a[0,:,I].T

In [91]: b
Out[91]: 
array([[ 0.,  0.,  1.,  1.],
       [ 0.,  0.,  1.,  1.],
       [ 0.,  0.,  1.,  1.]])

In [92]: b[:,I]=a[0][:,I]

https://github.com/numpy/numpy/issues/7030

https://github.com/numpy/numpy/pull/6256