问题描述
我正在尝试使用花哨的索引来修改大型稀疏矩阵。假设您有以下代码:
import numpy as np
import scipy.sparse as sp
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
b = sp.lil_matrix(a)
c = sp.lil_matrix((3,4))
c[[1,2],0] = b[[1,0]
ValueError: shape mismatch in assignment
我不明白为什么这不起作用。两个矩阵具有相同的形状,如果两个矩阵都是 numpy 数组,这通常有效。我将不胜感激。
解决方法
是的,这是稀疏 __setitem__
的错误。我以前遇到过它(但我只是解决了它)。现在我真的研究了它;首先,你可以很容易地解决这个问题:
import numpy as np
import scipy.sparse as sp
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
b = sp.lil_matrix(a)
c = sp.lil_matrix((3,4))
c[[1,2],0] = b[[1,0]
这会引发您看到的 ValueError
。这不会并且按预期工作:
c[[1,[0]]
>>> c.A
array([[0.,0.,0.],[5.,[9.,0.]])
让我们来看看 the offending __setitem__
(我将省略很多没有被调用的代码):
row,col = self._validate_indices(key)
这很好 - row = [1,2]
和 col = 0
col = np.atleast_1d(col)
i,j = _broadcast_arrays(row,col)
到目前为止一切顺利 - i = [1,2]
和 j = [0,0]
if i.ndim == 1:
# Inner indexing,so treat them like row vectors.
i = i[None]
j = j[None]
broadcast_row = x.shape[0] == 1 and i.shape[0] != 1
broadcast_col = x.shape[1] == 1 and i.shape[1] != 1
这是我们的问题 - i
和 j
都变成了形状为 (1,2)
的行向量。 x
此处是您要分配的内容 (b[[1,0]
),其形状为 (2,1)
;下一步引发 ValueError
原因 x
并且索引不对齐。
>>> c[[1,0].A
ValueError: cannot reshape array of size 4 into shape (2,)
这里有同样的问题,但 __setitem__
将 x
广播到 (2,2)
数组中,然后再次失败,因为它大于您分配给它的数组。
变通方法 (b[[1,[0]]
) 的形状为 (1,2)
,这是不正确的,但该错误最终抵消了索引 c
中的错误。
我不确定这个索引代码背后的逻辑到底是什么,所以我不确定如何在不引入其他细微错误的情况下解决这个问题。