Python 3.x 稀疏矩阵的元素划分

Python 3.x 稀疏矩阵的元素划分,python-3.x,scipy,sparse-matrix,elementwise-operations,Python 3.x,Scipy,Sparse Matrix,Elementwise Operations,我有一个大小为(nx m)的稀疏矩阵: 其中: num_documents=n 词汇表大小=m 数据=标记化列表的列表 此外,我还有一个长度为n的列表: sums=sparse\u dtm.sum(1.tolist() 现在,我想做一个元素级除法,其中稀疏dtm中行I的每个单元格被总和[I]除法 使用传统Python元素划分的简单方法: In [192]: M.sum(1) Out[192]: matrix([[4], [2], [1]]) In [193]

我有一个大小为(nx m)的稀疏矩阵:

其中:

  • num_documents=n
  • 词汇表大小=m
  • 数据=标记化列表的列表
此外,我还有一个长度为
n
的列表:

sums=sparse\u dtm.sum(1.tolist()

现在,我想做一个元素级除法,其中
稀疏dtm
行I
的每个单元格被
总和[I]
除法

使用传统Python元素划分的简单方法:

In [192]: M.sum(1)
Out[192]: 
matrix([[4],
        [2],
        [1]])
In [193]: M/M.sum(1)
Out[193]: 
matrix([[0.  , 0.25, 0.75, 0.  ],
        [0.  , 0.  , 1.  , 0.  ],
        [1.  , 0.  , 0.  , 0.  ]])
sparse\u dtm/sums

导致以下错误:

TypeError:/:“csr\u矩阵”和“列表”的操作数类型不受支持。


如何执行此元素除法?

如果我理解正确,您需要将每行除以行的总和,对吗

在这种情况下,您需要重新调整总和

sparse_dtm / sparse_dtm.sum(1).reshape(-1, 1)
例如,您也可以使用pandas数据帧来执行此操作

row_num = 10
col_num = 5
sparse_dtm = np.ndarray((row_num, col_num), dtype=np.float32)
for row in range(row_num):
    for col in range(col_num):
        value = (row+1) * (col+2)
        sparse_dtm[row, col] = value
df = pd.DataFrame(sparse_dtm)
print(df)
给予

然后将每行除以行的和

df / df.sum(axis=1).values.reshape(-1, 1)
那就

     0     1    2     3    4
0  0.1  0.15  0.2  0.25  0.3
1  0.1  0.15  0.2  0.25  0.3
2  0.1  0.15  0.2  0.25  0.3
3  0.1  0.15  0.2  0.25  0.3
4  0.1  0.15  0.2  0.25  0.3
5  0.1  0.15  0.2  0.25  0.3
6  0.1  0.15  0.2  0.25  0.3
7  0.1  0.15  0.2  0.25  0.3
8  0.1  0.15  0.2  0.25  0.3
9  0.1  0.15  0.2  0.25  0.3
请注意,结果是密集的
np.matrix
,而不是稀疏的

如果a行和为0,这可能会出现问题,但对于您的构造,这可能是不可能的

我们可以通过首先将和转换为稀疏来保留稀疏结果。我使用的是相反的,因为没有稀疏的元素划分(所有这些0):


谢谢Max,你的第一个建议很有效。但是,我使用的是稀疏矩阵,因为使用常规矩阵时会遇到内存问题。因此,熊猫的数据帧建议在我的情况下不起作用。
sparse\u dtm.sum(1)
应该已经是一个(n,1)形状的
np.matrix
。无需重塑。@hpaulj with
np.ndarray
使用我定义的用于填充di nd数组的for循环,您的shape
sparse\u dtm.shape
等于
(10,5)
。如果你做了
sparse\u dtm.sum(1)
你有一个形状
sparse\u dtm.sum(1)
等于
(10,)
,但是你需要一个
(10,1)
的形状,正如你所说的,所以你必须重塑
。重塑(-1,1)
对于密集数组,
ndarray
你确实需要重塑,或者使用
keepdims
。但是你继续称它为
sparse\u dtm
,所以我假设它在OP创建时是
scipy.sparse
。@hpaulj啊,是的,对不起,你说得对没有
tolist
sums
是什么?
     0     1    2     3    4
0  0.1  0.15  0.2  0.25  0.3
1  0.1  0.15  0.2  0.25  0.3
2  0.1  0.15  0.2  0.25  0.3
3  0.1  0.15  0.2  0.25  0.3
4  0.1  0.15  0.2  0.25  0.3
5  0.1  0.15  0.2  0.25  0.3
6  0.1  0.15  0.2  0.25  0.3
7  0.1  0.15  0.2  0.25  0.3
8  0.1  0.15  0.2  0.25  0.3
9  0.1  0.15  0.2  0.25  0.3
In [189]: M = sparse.dok_matrix([[0,1,3,0],[0,0,2,0],[1,0,0,0]])
In [190]: M
Out[190]: 
<3x4 sparse matrix of type '<class 'numpy.int64'>'
    with 4 stored elements in Dictionary Of Keys format>
In [191]: M.A
Out[191]: 
array([[0, 1, 3, 0],
       [0, 0, 2, 0],
       [1, 0, 0, 0]])
In [192]: M.sum(1)
Out[192]: 
matrix([[4],
        [2],
        [1]])
In [193]: M/M.sum(1)
Out[193]: 
matrix([[0.  , 0.25, 0.75, 0.  ],
        [0.  , 0.  , 1.  , 0.  ],
        [1.  , 0.  , 0.  , 0.  ]])
In [205]: D=sparse.csr_matrix(1/M.sum(1))
In [206]: D
Out[206]: 
<3x1 sparse matrix of type '<class 'numpy.float64'>'
    with 3 stored elements in Compressed Sparse Row format>
In [207]: D.A
Out[207]: 
array([[0.25],
       [0.5 ],
       [1.  ]])
In [208]: D.multiply(M)
Out[208]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>'
    with 4 stored elements in Compressed Sparse Row format>
In [209]: _.A
Out[209]: 
array([[0.  , 0.25, 0.75, 0.  ],
       [0.  , 0.  , 1.  , 0.  ],
       [1.  , 0.  , 0.  , 0.  ]])
In [210]: from sklearn import preprocessing
In [211]: preprocessing.normalize(M, norm='l1', axis=1)
Out[211]: 
<3x4 sparse matrix of type '<class 'numpy.float64'>'
    with 4 stored elements in Compressed Sparse Row format>
In [212]: _.A
Out[212]: 
array([[0.  , 0.25, 0.75, 0.  ],
       [0.  , 0.  , 1.  , 0.  ],
       [1.  , 0.  , 0.  , 0.  ]])