【问题标题】:Get unique rows from a Scipy sparse matrix从 Scipy 稀疏矩阵中获取唯一行
【发布时间】:2017-09-09 03:23:47
【问题描述】:

我正在使用 python 中的稀疏矩阵,我想知道是否有一种有效的方法可以删除稀疏矩阵中的重复行,并且只保留唯一的行。

我没有找到与之关联的函数,并且不确定如何在不将稀疏矩阵转换为密集矩阵并使用 numpy.unique 的情况下执行此操作。

【问题讨论】:

  • scipy 中没有任何内容。 np.unique 与新的 axis 参数可能是最好的路线。如果您必须坚持使用sparse,我建议您查看lil 格式及其“原始”行和数据属性。

标签: python numpy scipy sparse-matrix


【解决方案1】:

没有快速的方法,所以我不得不写一个函数。它返回一个稀疏矩阵,其中包含输入稀疏矩阵的唯一行 (axis=0) 或列 (axis=1)。 请注意,返回矩阵的唯一行或列不是按字典顺序排序的(np.unique 就是这种情况)。

import numpy as np
import scipy.sparse as sp

def sp_unique(sp_matrix, axis=0):
    ''' Returns a sparse matrix with the unique rows (axis=0)
    or columns (axis=1) of an input sparse matrix sp_matrix'''
    if axis == 1:
        sp_matrix = sp_matrix.T

    old_format = sp_matrix.getformat()
    dt = np.dtype(sp_matrix)
    ncols = sp_matrix.shape[1]

    if old_format != 'lil':
        sp_matrix = sp_matrix.tolil()

    _, ind = np.unique(sp_matrix.data + sp_matrix.rows, return_index=True)
    rows = sp_matrix.rows[ind]
    data = sp_matrix.data[ind]
    nrows_uniq = data.shape[0]

    sp_matrix = sp.lil_matrix((nrows_uniq, ncols), dtype=dt)  #  or sp_matrix.resize(nrows_uniq, ncols)
    sp_matrix.data = data
    sp_matrix.rows = rows

    ret = sp_matrix.asformat(old_format)
    if axis == 1:
        ret = ret.T        
    return ret


def lexsort_row(A):
    ''' numpy lexsort of the rows, not used in sp_unique'''
    return A[np.lexsort(A.T[::-1])]

if __name__ == '__main__':    
    # Test
    # Create a large sparse matrix with elements in [0, 10]
    A = 10*sp.random(10000, 3, 0.5, format='csr')
    A = np.ceil(A).astype(int)

    # unique rows
    A_uniq = sp_unique(A, axis=0).toarray()
    A_uniq = lexsort_row(A_uniq)
    A_uniq_numpy = np.unique(A.toarray(), axis=0)
    assert (A_uniq == A_uniq_numpy).all()

    # unique columns
    A_uniq = sp_unique(A, axis=1).toarray()
    A_uniq = lexsort_row(A_uniq.T).T
    A_uniq_numpy = np.unique(A.toarray(), axis=1)
    assert (A_uniq == A_uniq_numpy).all()  

【讨论】:

  • Excellente réponse avec un code de qualité。谢谢!
【解决方案2】:

也可以使用切片

def remove_duplicate_rows(data):
    unique_row_indices, unique_columns = [], []
    for row_idx, row in enumerate(data):
        indices = row.indices.tolist()
        if indices not in unique_columns:
            unique_columns.append(indices)
            unique_row_indices.append(row_idx)
    return data[unique_row_indices]

当我在受监督的机器学习环境中时,我发现这特别有用。在那里,我的函数的输入是数据和标签。通过这种方法,我可以轻松返回

labels[unique_row_indices]

同时确保数据和标签在清理后保持一致。

【讨论】:

  • 请注意,此解决方案不适用于lil_matrix 格式; csr_matrix 为我工作。
  • 此外,这不仅会删除重复的行,还会所有具有重复列索引的行。例如。它将删除scipy.sparse.csr_matrix(np.array([[1,1],[2,2]])) 的第二行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 2017-03-26
  • 2023-04-10
  • 2017-07-21
  • 2011-11-28
  • 2017-07-02
相关资源
最近更新 更多