假设我有一个来自scipy.sparse的NxN矩阵M(lil_matrix或csr_matrix),我想将其变为(N+1)xN,其中对于0 <= i < N(和所有j),M_modified[i, j] = M[i, j],并且对于所有j,M[N, j] = 0。基本上,我想在M的底部添加一行零并保留矩阵的其余部分。是否有一种方法可以在不复制数据的情况下完成这个操作?
假设我有一个来自scipy.sparse的NxN矩阵M(lil_matrix或csr_matrix),我想将其变为(N+1)xN,其中对于0 <= i < N(和所有j),M_modified[i, j] = M[i, j],并且对于所有j,M[N, j] = 0。基本上,我想在M的底部添加一行零并保留矩阵的其余部分。是否有一种方法可以在不复制数据的情况下完成这个操作?
Scipy没有一种方法可以在不复制数据的情况下完成此操作,但是您可以通过更改定义稀疏矩阵的属性来自己完成。
csr_matrix由4个属性组成:
data:包含矩阵中实际值的数组
indices:包含与data中每个值对应的列索引的数组
indptr:指定每行第一个值之前的索引的数组。如果该行为空,则索引与上一列相同。
shape:包含矩阵形状的元组
如果您只是在底部添加了一行零,则只需更改矩阵的形状和indptr即可。
x = np.ones((3,5))
x = csr_matrix(x)
x.toarray()
>> array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.]])
# reshape is not implemented for csr_matrix but you can cheat and do it yourself.
x._shape = (4,5)
# Update indptr to let it know we added a row with nothing in it. So just append the last
# value in indptr to the end.
# note that you are still copying the indptr array
x.indptr = np.hstack((x.indptr,x.indptr[-1]))
x.toarray()
array([[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.]])
这里是一个处理任意两个csr矩阵进行垂直拼接的函数。你仍然需要复制底层的numpy数组,但它仍然比scipy的vstack方法快得多。
def csr_vappend(a,b):
""" Takes in 2 csr_matrices and appends the second one to the bottom of the first one.
Much faster than scipy.sparse.vstack but assumes the type to be csr and overwrites
the first matrix instead of copying it. The data, indices, and indptr still get copied."""
a.data = np.hstack((a.data,b.data))
a.indices = np.hstack((a.indices,b.indices))
a.indptr = np.hstack((a.indptr,(b.indptr + a.nnz)[1:]))
a._shape = (a.shape[0]+b.shape[0],b.shape[1])
return a
a
,因为函数参数是通过引用传递的,即使在函数范围内,a
也会直接被修改。另外,是否有一个类似于csc_happend(a,b)的模拟函数? - richizy不确定您是否仍在寻找解决方案,但也许其他人可以看一下hstack
和vstack
- http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.hstack.html。我认为我们可以为单个附加行定义csr_matrix,然后使用vstack
与先前的矩阵叠加。
我认为无法从复制中真正逃脱。这两种类型的稀疏矩阵将它们的数据作为Numpy数组存储(在csr的数据和索引属性中,在lil的数据和行属性中),Numpy数组不能扩展。
更多信息更新:
LIL确实代表链表,但是当前实现并不完全符合名称。用于data
和rows
的Numpy数组都是对象类型。这些数组中的每个对象实际上都是Python列表(当一行中所有值为零时为空列表)。 Python列表并不完全是链表,但它们很接近,而且由于O(1)查找,它们是更好的选择。就我个人而言,我并没有立即看出在此处使用Numpy对象数组的意义,而不仅仅是Python列表。您可以相当容易地更改当前的lil实现以使用Python列表,这将使您能够添加行而无需复制整个矩阵。