2016-09-25 2 views
2

私はcsr_matrix形式の疎行列を持っています。各行について、私は非ゼロ要素から行平均を引く必要があります。この手段は、行の長さではなく、行の非ゼロ要素の数で計算する必要があります。scipy.sparse行列:0以外の要素への行平均の減算

# M is a csr_matrix 
sums = np.squeeze(np.asarray(M.sum(1))) # sum of the nonzero elements, for each row 
counts = np.diff(M.tocsr().indptr)   # count of the nonzero elements, for each row 


# for the i-th row the mean is just sums[i]/float(counts[i]) 

問題はアップデートの一部です: 私は、行を計算するための高速な方法は、次のコードを意味しました。私はこれを行うには速い方法が必要です。 は実際に私がやっている何lil_matrixにMを変換し、この方法でアップデートを実行することです:

M = M.tolil() 

for i in xrange(len(sums)): 
    for j in M.getrow(i).nonzero()[1]: 
     M[i, j] -= sums[i]/float(counts[i]) 

遅くなります。より高速なソリューションの提案はありますか?

+0

'' np.repeat'と 'counts'を使って行を複製しようとしています。そして、' M.data'配列から直接その行を複製しようとします。 – hpaulj

答えて

2

これは難しいです。私はそれを持っていると思う。基本的な考え方は、対角線上の手段で対角行列を得ようとすることです。行列はMに似ていますが、Mの非ゼロのデータ位置に行列を持ちます。次にそれらを掛け、Mからの積を減算します。行く...

>>> import numpy as np 
>>> import scipy.sparse as sp 
>>> a = sp.csr_matrix([[1., 0., 2.], [1.,2.,3.]]) 
>>> a.todense() 
matrix([[ 1., 0., 2.], 
     [ 1., 2., 3.]]) 
>>> tot = np.array(a.sum(axis=1).squeeze())[0] 
>>> tot 
array([ 3., 6.]) 
>>> cts = np.diff(a.indptr) 
>>> cts 
array([2, 3], dtype=int32) 
>>> mu = tot/cts 
>>> mu 
array([ 1.5, 2. ]) 
>>> d = sp.diags(mu, 0) 
>>> d.todense() 
matrix([[ 1.5, 0. ], 
     [ 0. , 2. ]]) 
>>> b = a.copy() 
>>> b.data = np.ones_like(b.data) 
>>> b.todense() 
matrix([[ 1., 0., 1.], 
     [ 1., 1., 1.]]) 
>>> (d * b).todense() 
matrix([[ 1.5, 0. , 1.5], 
     [ 2. , 2. , 2. ]]) 
>>> (a - d*b).todense() 
matrix([[-0.5, 0. , 0.5], 
     [-1. , 0. , 1. ]]) 

おはよう!希望が役立ちます。 @Dthal'sサンプルを皮切り

+0

はい、私は同じことを考えていました。ありがとうございました! – revy

2

In [92]: a = sparse.csr_matrix([[1.,0,2],[1,2,3]]) 
In [93]: a.A 
Out[93]: 
array([[ 1., 0., 2.], 
     [ 1., 2., 3.]]) 

In [94]: sums=np.squeeze(a.sum(1).A) 
# sums=a.sum(1).A1 # shortcut 
In [95]: counts=np.diff(a.tocsr().indptr) 
In [96]: means=sums/counts 
In [97]: sums 
Out[97]: array([ 3., 6.]) 
In [98]: counts 
Out[98]: array([2, 3], dtype=int32) 
In [99]: means 
Out[99]: array([ 1.5, 2. ]) 

repeatは、私たちは、サイズが行列dataに一致する配列を生成、meansを複製することができます。このmc

In [100]: mc = np.repeat(means, counts) 
In [101]: mc 
Out[101]: array([ 1.5, 1.5, 2. , 2. , 2. ]) 

@Dthal's(b*d).dataと同じです。

ここで、それをdataから引きます。

In [102]: a.data -= mc 
In [103]: a.A 
Out[103]: 
array([[-0.5, 0. , 0.5], 
     [-1. , 0. , 1. ]]) 
関連する問題