稀疏矩阵中非零值的均值是多少?

5
我正在尝试计算稀疏行矩阵中每一行非零值的平均值。使用矩阵的平均方法并不能实现此目的:
>>> from scipy.sparse import csr_matrix
>>> a = csr_matrix([[0, 0, 2], [1, 3, 8]])
>>> a.mean(axis=1)
matrix([[ 0.66666667],
        [ 4.        ]])

以下方法对于较大的矩阵来说是可以工作的,但速度较慢:
>>> import numpy as np
>>> b = np.zeros(a.shape[0])
>>> for i in range(a.shape[0]):
...    b[i] = a.getrow(i).data.mean()
... 
>>> b
array([ 2.,  4.])

请问有更快的方法吗?

4个回答

9
使用CSR格式矩阵,甚至可以更轻松地完成此操作:
sums = a.sum(axis=1).A1
counts = np.diff(a.indptr)
averages = sums / counts

CSR格式直接支持行求和操作,而且该格式的结构意味着indptr数组中相邻值之间的差正好对应于每行非零元素的数量。


避免除以零错误的最佳方法是什么?我在除法之前添加了这个:counts[counts == 0] = 1,但不知道是否是最好的选择。逻辑是,如果计数为0,则总和在该位置上也必须为0。因此,如果我们想保持为0,则无论我们除以什么都无所谓。 - Luca Guarro

6

这似乎是一个典型的问题,可以使用numpy.bincount解决。为此,我使用了三个函数:

(x,y,z)=scipy.sparse.find(a)

返回稀疏矩阵的行(x)、列(y)和值(z)。例如,xarray([0, 1, 1, 1].

numpy.bincount(x) 返回每行元素非零的数量。

numpy.bincount(x,wights=z) 返回每行非零元素的总和。

最终可用代码:

from scipy.sparse import csr_matrix
a = csr_matrix([[0, 0, 2], [1, 3, 8]])

import numpy
import scipy.sparse
(x,y,z)=scipy.sparse.find(a)
countings=numpy.bincount(x)
sums=numpy.bincount(x,weights=z)
averages=sums/countings

print(averages)

返回值:

[ 2.  4.]

3

我通常喜欢将感兴趣的轴上的数值相加,然后除以相应行/列中非零元素的总数。

就像这样:

sp_arr = csr_matrix([[0, 0, 2], [1, 3, 8]])
col_avg = sp_arr.sum(0) / (sp_arr != 0).sum(0)
row_avg = sp_arr.sum(1) / (sp_arr != 0).sum(1)
print(col_avg)
matrix([[ 1.,  3.,  5.]])
print(row_avg)
matrix([[ 2.],
        [ 4.]])

基本上,您正在对给定轴上的所有条目的总值进行求和,并将其除以矩阵!=0(即实际条目数)时 True 条目的总和。

我发现这种方法比其他选项更简单易行。


1
我也喜欢这种方法,已点赞。一个改进是通过使用nnz来避免形成x != 0(可能会占用大量内存)的矩阵。 - user39430

2
一个返回平均值列表的简单方法:
a.sum(axis=0) / a.getnnz(axis=0)

假设矩阵中没有明确的零元素。 如果需要,可以更改轴。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接