我有一个很大的csr_matrix,我想添加行并获得一个新的csr_matrix,其列数相同但行数减少。 (上下文:矩阵是从sklearn CountVectorizer获得的文档术语矩阵,我希望能够根据与这些文档相关的代码快速组合文档)
对于一个最小的例子,这是我的矩阵:
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse import vstack
row = np.array([0, 4, 1, 3, 2])
col = np.array([0, 2, 2, 0, 1])
dat = np.array([1, 2, 3, 4, 5])
A = csr_matrix((dat, (row, col)), shape=(5, 5))
print A.toarray()
[[1 0 0 0 0]
[0 0 3 0 0]
[0 5 0 0 0]
[4 0 0 0 0]
[0 0 2 0 0]]
不,我想要一个新的矩阵B
,其中行(1,4)和(2,3,5)通过求和来组合,这看起来像这样:
[[5 0 0 0 0]
[0 5 5 0 0]]
并且应该再次采用稀疏格式(因为我正在使用的真实数据很大)。我试图对矩阵的切片求和,然后将其叠加:
idx1 = [1, 4]
idx2 = [2, 3, 5]
A_sub1 = A[idx1, :].sum(axis=1)
A_sub2 = A[idx2, :].sum(axis=1)
B = vstack((A_sub1, A_sub2))
但是这给出了切片中非零列的总和值,因此我无法将其与其他切片组合,因为求和切片中的列数不同。
我觉得必须有一个简单的方法来做到这一点。但我在网上或文档中找不到任何关于此的讨论。我错过了什么?
感谢您的帮助
答案 0 :(得分:4)
请注意,您可以通过仔细构建另一个矩阵来完成此操作。以下是密集矩阵的工作原理:
>>> S = np.array([[1, 0, 0, 1, 0,], [0, 1, 1, 0, 1]])
>>> np.dot(S, A.toarray())
array([[5, 0, 0, 0, 0],
[0, 5, 5, 0, 0]])
>>>
稀疏版本只是稍微复杂一点。有关哪些行应汇总在一起的信息在row
:
col = range(5)
row = [0, 1, 1, 0, 1]
dat = [1, 1, 1, 1, 1]
S = csr_matrix((dat, (row, col)), shape=(2, 5))
result = S * A
# check that the result is another sparse matrix
print type(result)
# check that the values are the ones we want
print result.toarray()
输出:
<class 'scipy.sparse.csr.csr_matrix'>
[[5 0 0 0 0]
[0 5 5 0 0]]
您可以在row
中包含更高的值并相应地扩展S
的形状,从而处理输出中的更多行。
答案 1 :(得分:1)
索引应为:
idx1 = [0, 3] # rows 1 and 4
idx2 = [1, 2, 4] # rows 2,3 and 5
然后,您需要以稀疏格式保留A_sub1
和A_sub2
并使用axis=0
:
A_sub1 = csr_matrix(A[idx1, :].sum(axis=0))
A_sub2 = csr_matrix(A[idx2, :].sum(axis=0))
B = vstack((A_sub1, A_sub2))
B.toarray()
array([[5, 0, 0, 0, 0],
[0, 5, 5, 0, 0]])
注意,我认为A[idx, :].sum(axis=0)
操作涉及从稀疏矩阵转换 - 所以@ Mr_E的答案可能更好。
或者,当您使用axis=0
和np.vstack
(而不是scipy.sparse.vstack
)时,它会有效:
A_sub1 = A[idx1, :].sum(axis=0)
A_sub2 = A[idx2, :].sum(axis=0)
np.vstack((A_sub1, A_sub2))
,并提供:
matrix([[5, 0, 0, 0, 0],
[0, 5, 5, 0, 0]])