スパース行列の場合はnumpy.delete()が同じですか? -- python フィールド と numpy フィールド と scipy フィールド 関連 問題

Is there a numpy.delete() equivalent for sparse matrices?












23
vote

問題

日本語

numpy配列として2次元行列を持っているとしましょう。この行列の特定のインデックスを持つ行を削除したい場合は、 numpy.delete() 。これは私が何を意味するのかの例です:

<事前> <コード> In [1]: my_matrix = numpy.array([ ...: [10, 20, 30, 40, 50], ...: [15, 25, 35, 45, 55], ...: [95, 96, 97, 98, 99] ...: ]) In [2]: numpy.delete(my_matrix, [0, 2], axis=0) Out[2]: array([[15, 25, 35, 45, 55]])

<コード> scipy.sparse パッケージ。行列全体をNumPy配列に変換することでこれを行うことが可能ですが、それをしたくありません。その他の方法はありますか?

たくさんありがとう!

英語

Let's say I have a 2-dimensional matrix as a numpy array. If I want to delete rows with specific indices in this matrix, I use numpy.delete(). Here is an example of what I mean:

In [1]: my_matrix = numpy.array([    ...:     [10, 20, 30, 40, 50],    ...:     [15, 25, 35, 45, 55],    ...:     [95, 96, 97, 98, 99]    ...: ]) In [2]: numpy.delete(my_matrix, [0, 2], axis=0) Out[2]: array([[15, 25, 35, 45, 55]]) 

I'm looking for a way to do the above with matrices from the scipy.sparse package. I know it's possible to do this by converting the entire matrix into a numpy array but I don't want to do that. Is there any other way of doing that?

Thanks a lot!

</div
        

回答リスト

25
 
vote

CSRの場合、これはおそらくその場で最も効率的な方法です。

<事前> <コード> def delete_row_csr(mat, i): if not isinstance(mat, scipy.sparse.csr_matrix): raise ValueError("works only for CSR format -- use .tocsr() first") n = mat.indptr[i+1] - mat.indptr[i] if n > 0: mat.data[mat.indptr[i]:-n] = mat.data[mat.indptr[i+1]:] mat.data = mat.data[:-n] mat.indices[mat.indptr[i]:-n] = mat.indices[mat.indptr[i+1]:] mat.indices = mat.indices[:-n] mat.indptr[i:-1] = mat.indptr[i+1:] mat.indptr[i:] -= n mat.indptr = mat.indptr[:-1] mat._shape = (mat._shape[0]-1, mat._shape[1])

LIL形式ではさらに簡単です:

<事前> <コード> def delete_row_lil(mat, i): if not isinstance(mat, scipy.sparse.lil_matrix): raise ValueError("works only for LIL format -- use .tolil() first") mat.rows = np.delete(mat.rows, i) mat.data = np.delete(mat.data, i) mat._shape = (mat._shape[0] - 1, mat._shape[1])
 

For CSR, this is probably the most efficient way to do it in-place:

def delete_row_csr(mat, i):     if not isinstance(mat, scipy.sparse.csr_matrix):         raise ValueError("works only for CSR format -- use .tocsr() first")     n = mat.indptr[i+1] - mat.indptr[i]     if n > 0:         mat.data[mat.indptr[i]:-n] = mat.data[mat.indptr[i+1]:]         mat.data = mat.data[:-n]         mat.indices[mat.indptr[i]:-n] = mat.indices[mat.indptr[i+1]:]         mat.indices = mat.indices[:-n]     mat.indptr[i:-1] = mat.indptr[i+1:]     mat.indptr[i:] -= n     mat.indptr = mat.indptr[:-1]     mat._shape = (mat._shape[0]-1, mat._shape[1]) 

In LIL format it's even simpler:

def delete_row_lil(mat, i):     if not isinstance(mat, scipy.sparse.lil_matrix):         raise ValueError("works only for LIL format -- use .tolil() first")     mat.rows = np.delete(mat.rows, i)     mat.data = np.delete(mat.data, i)     mat._shape = (mat._shape[0] - 1, mat._shape[1]) 
</div
 
 
12
 
vote

PV.SENSWEは、

を取ります優しい固体の溶液です。 <事前> <コード> a = scipy.sparse.csr_matrix((100,100), dtype=numpy.int8) %timeit delete_row_csr(a.copy(), 0) 10000 loops, best of 3: 80.3 us per loop

任意の配列サイズです。ブールインデックスは、少なくとも<コード> scipy >= 0.14.0 で、スパース行列のために機能するので、複数行を削除するときはいつでもそれを使用することをお勧めします。

<事前> <コード> def delete_rows_csr(mat, indices): """ Remove the rows denoted by ``indices`` form the CSR sparse matrix ``mat``. """ if not isinstance(mat, scipy.sparse.csr_matrix): raise ValueError("works only for CSR format -- use .tocsr() first") indices = list(indices) mask = numpy.ones(mat.shape[0], dtype=bool) mask[indices] = False return mat[mask]

この解決策は単一行の取り外しのためにかなり長くかかる

<事前> <コード> %timeit delete_rows_csr(a.copy(), [50]) 1000 loops, best of 3: 509 us per loop 実行時間がかろうじて行数が大きくなるにつれて、複数行の削除にはより効率的です。 <事前> <コード> %timeit delete_rows_csr(a.copy(), numpy.random.randint(0, 100, 30)) 1000 loops, best of 3: 523 us per loop
 

Pv.s answer is a good and solid in-place solution that takes

a = scipy.sparse.csr_matrix((100,100), dtype=numpy.int8) %timeit delete_row_csr(a.copy(), 0) 10000 loops, best of 3: 80.3 us per loop 

for any array size. Since boolean indexing works for sparse matrices, at least in scipy >= 0.14.0, I would suggest to use it whenever multiple rows are to be removed:

def delete_rows_csr(mat, indices):     """     Remove the rows denoted by ``indices`` form the CSR sparse matrix ``mat``.     """     if not isinstance(mat, scipy.sparse.csr_matrix):         raise ValueError("works only for CSR format -- use .tocsr() first")     indices = list(indices)     mask = numpy.ones(mat.shape[0], dtype=bool)     mask[indices] = False     return mat[mask] 

This solution takes significantly longer for a single row removal

%timeit delete_rows_csr(a.copy(), [50]) 1000 loops, best of 3: 509 us per loop 

But is more efficient for the removal of multiple rows, as the execution time barely increases with the number of rows

%timeit delete_rows_csr(a.copy(), numpy.random.randint(0, 100, 30)) 1000 loops, best of 3: 523 us per loop 
</div
 
 
 
 
7
 
vote

@ Loliの版の@ PVの答えに加えて、私は彼らの関数を拡張して、および/または列の削除がCSR行列のインデックスによる列削除を許可しました。 <コード> import numpy as np from scipy.sparse import csr_matrix def delete_from_csr(mat, row_indices=[], col_indices=[]): """ Remove the rows (denoted by ``row_indices``) and columns (denoted by ``col_indices``) from the CSR sparse matrix ``mat``. WARNING: Indices of altered axes are reset in the returned matrix """ if not isinstance(mat, csr_matrix): raise ValueError("works only for CSR format -- use .tocsr() first") rows = [] cols = [] if row_indices: rows = list(row_indices) if col_indices: cols = list(col_indices) if len(rows) > 0 and len(cols) > 0: row_mask = np.ones(mat.shape[0], dtype=bool) row_mask[rows] = False col_mask = np.ones(mat.shape[1], dtype=bool) col_mask[cols] = False return mat[row_mask][:,col_mask] elif len(rows) > 0: mask = np.ones(mat.shape[0], dtype=bool) mask[rows] = False return mat[mask] elif len(cols) > 0: mask = np.ones(mat.shape[1], dtype=bool) mask[cols] = False return mat[:,mask] else: return mat

 

In addition to @loli's version of @pv's answer, I expanded their function to allow for row and/or column deletion by index on CSR matrices.

import numpy as np from scipy.sparse import csr_matrix  def delete_from_csr(mat, row_indices=[], col_indices=[]):     """     Remove the rows (denoted by ``row_indices``) and columns (denoted by ``col_indices``) from the CSR sparse matrix ``mat``.     WARNING: Indices of altered axes are reset in the returned matrix     """     if not isinstance(mat, csr_matrix):         raise ValueError("works only for CSR format -- use .tocsr() first")      rows = []     cols = []     if row_indices:         rows = list(row_indices)     if col_indices:         cols = list(col_indices)      if len(rows) > 0 and len(cols) > 0:         row_mask = np.ones(mat.shape[0], dtype=bool)         row_mask[rows] = False         col_mask = np.ones(mat.shape[1], dtype=bool)         col_mask[cols] = False         return mat[row_mask][:,col_mask]     elif len(rows) > 0:         mask = np.ones(mat.shape[0], dtype=bool)         mask[rows] = False         return mat[mask]     elif len(cols) > 0:         mask = np.ones(mat.shape[1], dtype=bool)         mask[cols] = False         return mat[:,mask]     else:         return mat 
</div
 
 
     
     
5
 
vote

CSR行列から<コード> 0 < i < X.shape[0] - 1 を削除できます。 X

<事前> <コード> scipy.sparse.vstack([X[:i, :], X[i:, :]])

X[1:, :] または X[:-1, :] でそれぞれ、最初の行を削除することができます。 1つの消去に複数の行を削除すると、おそらくあなた自身の機能を転がす必要があります。

CSR以外のフォーマットでは、これは必ずしもすべてのフォーマットをサポートするわけではないとは限りません。

 

You can delete row 0 < i < X.shape[0] - 1 from a CSR matrix X with

scipy.sparse.vstack([X[:i, :], X[i:, :]]) 

You can delete the first or the last row with X[1:, :] or X[:-1, :], respectively. Deleting multiple rows in one gone will probably require rolling your own function.

For other formats than CSR, this might not necessarily work as not all formats support row slicing.

</div
 
 
   
   
5
 
vote

左の行列乗算を単に使用するだけでi番目の行を削除する:

<事前> <コード> B = J*A

ここで、jはi番目の行を削除したスパースアイデンティティマトリックスです。
jの転置による左乗算は、Bのi行目にゼロベクトルを挿入します。これはこの解決策をもう少し一般的にします。

<事前> <コード> A0 = J.T * B

J自体を構築するために、私は以下のように疎角行列上のPVを使用した(多数の特別な場合にはより単純な解決策がある?)

<事前> <コード> def identity_minus_rows(N, rows): if np.isscalar(rows): rows = [rows] J = sps.diags(np.ones(N), 0).tocsr() # make a diag matrix for r in sorted(rows): J = delete_row_csr(J, r) return J

適切なサイズのj.tで右乗算で列を削除することもできます。
最後に、この場合、jは非常にスパースであるため、乗算は効率的です。

 

To remove the i'th row from A simply use left matrix multiplication:

B = J*A 

where J is a sparse identity matrix with i'th row removed.
Left multiplication by the transpose of J will insert a zero-vector back to the i'th row of B, which makes this solution a bit more general.

A0 = J.T * B 

To construct J itself, I used pv.'s solution on a sparse diagonal matrix as follows (maybe there's a simpler solution for this special case?)

def identity_minus_rows(N, rows):     if np.isscalar(rows):         rows = [rows]     J = sps.diags(np.ones(N), 0).tocsr()  # make a diag matrix     for r in sorted(rows):         J = delete_row_csr(J, r)     return J 

You may also remove columns by right-multiplying by J.T of the appropriate size.
Finally, multiplication is efficient in this case because J is so sparse.

</div
 
 
     
     
2
 
vote

スパース行列は、ある程度の派手な索引付けをサポートしています。それであなたができることはこれです:

<事前> <コード> mask = np.ones(len(mat), dtype=bool) mask[rows_to_delete] = False # unfortunatly I think boolean indexing does not work: w = np.flatnonzero(mask) result = s[w,:]

削除方法は他に何もしない。

 

Note that sparse matrices support fancy indexing to some degree. So what you can do is this:

mask = np.ones(len(mat), dtype=bool) mask[rows_to_delete] = False # unfortunatly I think boolean indexing does not work: w = np.flatnonzero(mask) result = s[w,:] 

The delete method doesn't really do anything else either.

</div
 
 
1
 
vote

@LOLI実装を使用すると、ここで列を削除する関数を残します。

<事前> <コード> def delete_cols_csr(mat, indices): """ Remove the cols denoted by ``indices`` form the CSR sparse matrix ``mat``. """ if not isinstance(mat, csr_matrix): raise ValueError("works only for CSR format -- use .tocsr() first") indices = list(indices) mask = np.ones(mat.shape[1], dtype=bool) mask[indices] = False return mat[:,mask]
 

Using @loli implementation, here I leave a function to remove columns:

def delete_cols_csr(mat, indices):     """     Remove the cols denoted by ``indices`` form the CSR sparse matrix ``mat``.     """     if not isinstance(mat, csr_matrix):         raise ValueError("works only for CSR format -- use .tocsr() first")     indices = list(indices)     mask = np.ones(mat.shape[1], dtype=bool)     mask[indices] = False     return mat[:,mask] 
</div
 
 

関連する質問

3  Scipy:半円の上の暴動の間伐?  ( Scipy von mises distribution on a half circle ) 
半円の上に包まれたVon-Misesディストリビューションを定義するための最良の方法を見つけようとしています(私はそれを使って方向のない線を描くために使います)。私は現在Scipyのvonmiss.rvs()を使用しています。基本的に、私は、PI / 2の平均...

16  ScipyMinize Handle NaNをどのようにしていますか?  ( How does scipy minimize handle nans ) 
SCIPYMINIMIZEのSLSQPソルバーを使用して、制約付き最適化問題を解決しています。非常に頻繁にソルバーは制約に違反するパラメータ値を試みます。これらの制約が違反されると、目的関数は nan を返します。私の近似ヤコビアンは、再計算されるたびに n...

10  ネストしたループをスピードアップする方法  ( How to speed up nested loop ) 
下記に含まれるPythonにネストしたループを実行しています。これは、既存の金融時系列を検索し、特定の特性に一致する時系列の期間を探している基本的な方法として機能します。 この場合、「閉じる」(すなわち、資産の価格)および「ボリューム」を表す2つの別々の、等...

17  NUMPY / SCIPYスパースと高密度行列を効率的に掛ける  ( Multiplying numpy scipy sparse and dense matrices efficiently ) 
次の式を実装するために作業しています: <事前> <コード> X =(Y.T * Y + Y.T * C * Y) ^ -1 yは(n x f)行列であり、cは(n x n)対角のものである。 nは約300kであり、fは100から200の間で変化します。...

1  polyfit()は予期しないキーワード引数 'w'を得ました  ( Polyfit got an unexpected keyword argument w ) 
np.polyfit を使用しようとしています。 <事前> <コード> TypeError: polyfit() got an unexpected keyword argument 'w' documentation その関数は明らかにこれを言っ...

0  CythonでコンパイルScipy機能  ( Compile scipy function with cython ) 
Python 3.4でシミュレーションを実行しています - スパースアレイ(CSR形式)と密なベクトルの間にたくさんのドット製品を含みます。私はスパース行列のScipyを使っています、他のすべてのためにnumpy。 Cythonを使用すると、私がすべてが...

4  Sklearnのロジスティック回帰機能  ( Logistic regression function on sklearn ) 
Sklearnからロジスティック回帰を学んで、これに渡って来ました: http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.logisticRegression.htmor...

0  列全体のマトリックスの2次ノルムを計算するためのNUMPY文書は、わずかに誤解を招くことですか?  ( Is the numpy documentation for calculating the 2nd order norm of a matrix across ) 
マトリックスのフロベニウスの計算方法をnumpyで把握しようとしていました。このようにして、以下の行列X内の各行の2ノルムを取得できます。 私の質問は、numpyの linalg.norm モジュールの ord パラメータ、および numpy文書の関連部分は、...

-1  SCIPY Solverはエラーを返します/ numpy.seterrの使い方は?  ( Scipy solver returns an error how to use numpy seterr ) 
このエラーが原因でどのように考えていますか? <事前> <コード> ParentId5 私のコードでは重要なものはありません、それは単なるScipyソルバー関数、具体的にはnewton_krylovです。私はエラーを追跡するためにnumpy.seterrを使...

1  畳み込み:2D対1D 2-PASSの異なる結果を与える  ( Convolution 2d vs 1d 2 pass giving different results ) 
理論的には、2D畳み込みは次のように分割できます。<コード> G(x,y)*I = G(x) * G(y)*I しかし私がこれを試してみると: <事前> <コード> import cv2 import scipy.signal as signal impo...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有