2015-12-14 2 views
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

Это кажется типичной проблемой, где вы можете использовать numpy.bincount. Для этого я использовал три функции:

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

возвращает строки (x), столбцы (y) и значение (z) из разреженной матрицы. Для instace, x is array([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.] 
+0

Отлично, спасибо – batsc

5

С матрицей формата CSR, вы можете сделать это еще проще:

sums = a.sum(axis=1).A1 
counts = np.diff(a.indptr) 
averages = sums/counts 

рядных суммами являются напрямую поддерживается, а структура формата CSR означает, что разница между последовательными значениями в indptr соответствуют точно количеству ненулевых элементов в каждой строке.

1

Мне всегда нравится суммировать значения по любой интересующей вас оси и делить на общее количество ненулевых элементов в соответствующей строке/столбце.

Как так:

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.]]) 

В основном вы суммируя общую стоимость всех записей вдоль заданной оси и деления суммы True записей, где матрица = 0 (что число реально! записей).

Я считаю этот подход более сложным и легким, чем другие варианты.

Смежные вопросы