2012-08-26 69 views
7

假設我有一個CSR格式的矩陣,將行(或行)設置爲零的最有效方法是什麼?scipy.sparse:將行設置爲零

下面的代碼運行很慢:

A = A.tolil() 
A[indices, :] = 0 
A = A.tocsr() 

我不得不因爲CSR格式似乎既不支持花哨的索引,也不值作爲片轉換爲scipy.sparse.lil_matrix

+0

好吧,我只是嘗試了'[A .__ setitem __((I,J),0)對於我在範圍內的j的索引(A.shape [1])]'和'SciPy'告訴我'SparseEfficiencyWarning:改變csr_matrix的稀疏結構是很昂貴的。 「...... –

+0

不知道scipy是否支持它,但由於它是一個CSR矩陣,所以可以有效地處理(至少手工處理)。一個問題是,你想改變稀疏模式,還是應該只是數字0? – seberg

+0

我不確定稀疏模式是什麼意思。我繼續使用scipy.sparse.linalg.spsolve函數來求解方程組。我希望這確立了改變稀疏模式或缺乏模式的需要。 –

回答

5

我猜SciPy的只是沒有實現它,但是CSR格式將支持此相當好,請閱讀關於「稀疏矩陣」維基百科的文章什麼indptr等都是:

# A.indptr is an array, one for each row (+1 for the nnz): 

def csr_row_set_nz_to_val(csr, row, value=0): 
    """Set all nonzero elements (elements currently in the sparsity pattern) 
    to the given value. Useful to set to 0 mostly. 
    """ 
    if not isinstance(csr, scipy.sparse.csr_matrix): 
     raise ValueError('Matrix given must be of CSR format.') 
    csr.data[csr.indptr[row]:csr.indptr[row+1]] = value 

# Now you can just do: 
for row in indices: 
    csr_row_set_nz_to_val(A, row, 0) 

# And to remove zeros from the sparsity pattern: 
A.eliminate_zeros() 

當然這會從稀疏模式中刪除從另一位置eliminate_zeros設置的0。如果你想這樣做(在這一點上)取決於你在做什麼,即。消除可能是有意義的,直到所有其他可能會添加新零的計算都完成爲止,或者在某些情況下,您可能有0個值,以後要再次更改,所以消除它們將會非常糟糕!

原則上你當然可以將eliminate_zerosprune短路,但這應該是很多麻煩,甚至可能會更慢(因爲你不會在C中)。約eliminiate_zeros(和刪節)


詳細

的稀疏矩陣,通常不會保存零個元素,但只是其中存儲非零元素是(大致與各種方法)。 eliminate_zeros從稀疏模式中刪除矩陣中的所有零(即沒有爲該位置存儲的值,當在之前存儲了vlaue,但它是0)。如果您希望稍後將0更改爲不同的值,則消除效果很差,否則會節省空間。

修剪只會收縮存儲的數據數組,然後它們需要更長的時間。請注意,雖然我第一次有A.prune()那裏,A.eliminiate_zeros()已經包括修剪。

+0

謝謝!這大大加快了事情!我只想知道在那裏使用的except_zeros和prune語句在做什麼? –

+0

添加了一個(希望能夠理解的)句子。請注意,'prune()'是不必要的,''remove_zeros'已經調用'prune' – seberg

0

更新到最新版本的scipy。它支持花哨的索引。

0

您可以使用矩陣點產品來實現該調零。由於我們將使用的矩陣非常稀疏(對角線,對於零/零列的行/列爲零),因此乘法應該是有效的。

你需要以下功能之一:

import scipy.sparse 

def zero_rows(M, rows): 
    diag = scipy.sparse.eye(M.shape[0]).tolil() 
    for r in rows: 
     diag[r, r] = 0 
    return diag.dot(M) 

def zero_columns(M, columns): 
    diag = scipy.sparse.eye(M.shape[1]).tolil() 
    for c in columns: 
     diag[c, c] = 0 
    return M.dot(diag) 

用例:

>>> A = scipy.sparse.csr_matrix([[1,0,3,4], [5,6,0,8], [9,10,11,0]]) 
>>> A 
<3x4 sparse matrix of type '<class 'numpy.int64'>' 
     with 9 stored elements in Compressed Sparse Row format> 
>>> A.toarray() 
array([[ 1, 0, 3, 4], 
     [ 5, 6, 0, 8], 
     [ 9, 10, 11, 0]], dtype=int64) 

>>> B = zero_rows(A, [1]) 
>>> B 
<3x4 sparse matrix of type '<class 'numpy.float64'>' 
     with 6 stored elements in Compressed Sparse Row format> 
>>> B.toarray() 
array([[ 1., 0., 3., 4.], 
     [ 0., 0., 0., 0.], 
     [ 9., 10., 11., 0.]]) 

>>> C = zero_columns(A, [1, 3]) 
>>> C 
<3x4 sparse matrix of type '<class 'numpy.float64'>' 
     with 5 stored elements in Compressed Sparse Row format> 
>>> C.toarray() 
array([[ 1., 0., 3., 0.], 
     [ 5., 0., 0., 0.], 
     [ 9., 0., 11., 0.]])