具有高级混合索引的Numpy子数组分配



原始问题

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

 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)的索引结果

--

跟进

使用slice和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]。

在复制要质疑的代码时似乎出现了一些错误。

但我怀疑索引有一个已知的问题:

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)

但对于3da,我们得到了转置。

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

首先,第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.]]

我怀疑这正是你想要的。

这里我得到了索引[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.]]

最新更新