25

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配列に変換することでこれを行うことができることは知っていますが、それはしたくありません。それを行う他の方法はありますか?

どうもありがとう!

4

7 に答える 7

26

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])
于 2012-10-25T23:21:58.297 に答える
13

Pv.s の回答は、優れた堅実なインプレース ソリューションです。

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]

このソリューションでは、1 行の削除にかなりの時間がかかります

%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
于 2014-10-22T10:04:35.900 に答える
6

0 < i < X.shape[0] - 1CSRマトリックスから行Xを削除できます

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

最初または最後の行をそれぞれX[1:, :]またはX[:-1, :]で削除できます。複数の行を一度に削除するには、おそらく独自の関数をロールする必要があります。

CSR 以外の形式の場合、すべての形式が行のスライスをサポートしているわけではないため、これは必ずしも機能しない可能性があります。

于 2012-10-25T21:34:13.490 に答える
2

スパース行列は、ファンシー インデックス付けをある程度サポートすることに注意してください。だからあなたができることはこれです:

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,:]

delete メソッドも実際には何もしません。

于 2012-10-26T10:07:02.193 に答える
2

@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]
于 2018-04-30T00:42:06.630 に答える