2015-12-14 4 views
5

Ich versuche, den Mittelwert von Nicht-Null-Werten in jeder Zeile einer Sparse-Zeile Matrix zu berechnen. Unter Verwendung der mittleren Methode der Matrix ist es nicht tun:Mittelwert von Nicht-Null-Werten in Sparse-Matrix?

>>> from scipy.sparse import csr_matrix 
>>> a = csr_matrix([[0, 0, 2], [1, 3, 8]]) 
>>> a.mean(axis=1) 
matrix([[ 0.66666667], 
     [ 4.  ]]) 

Folgende Werke, sondern ist für große Matrizen langsam:

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

Könnte jemand bitte sagen Sie mir, ob es eine schnellere Methode ist?

Antwort

4

Dies scheint das typische Problem, wo Sie numpy.bincount. Dazu benutze ich drei Funktionen gemacht verwenden können:

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

kehrt Zeilen (x), Spalten (y) und Werte (z) der Sparse-Matrix. Zum Beispiel x ist array([0, 1, 1, 1].

numpy.bincount(x) gibt für jede Zeilennummer zurück, wie meny nonzero elemnts Sie haben.

numpy.bincount(x,wights=z) gibt für jede Zeile die Summe der von Null verschiedenen Elemente zurück.

Ein abschließender Arbeitscode:

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) 

kehrt:

[ 2. 4.] 
+0

Ausgezeichnet, danke – batsc

5

Mit einer CSR-Format Matrix, können Sie dies noch leichter:

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

Row-Summen direkt unterstützt, und die Struktur des CSR-Format bedeutet, dass der Unterschied zwischen aufeinanderfolgenden Werten in der indptr Array entspricht genau der Anzahl der Elemente ungleich Null in jeder Zeile.

1

Ich möchte immer die Werte über jede Achse, die Sie interessieren, summieren und dividieren durch die Summe der Elemente ungleich Null in der entsprechenden Zeile/Spalte.

Wie so:

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

Grundsätzlich Sie den Gesamtwert aller Einträge entlang der gegebenen Achse summieren und durch die Summe der True Einträge abgrenzen, in denen die Matrix = 0 (was die Anzahl der real ist! Einträge).

Ich finde diesen Ansatz weniger kompliziert und einfacher als die anderen Optionen.

Verwandte Themen