【问题标题】:Delete columns of matrix of CSR format in Python在Python中删除CSR格式矩阵的列
【发布时间】:2014-07-20 22:35:15
【问题描述】:

我有一个 csr 格式的稀疏矩阵 (22000x97482),我想删除一些列(列号的索引存储在列表中)

【问题讨论】:

  • 这能回答你的问题吗? stackoverflow.com/questions/2368544/…
  • 不是真的,它是另一种格式的稀疏矩阵。我试过但没有结果
  • 我认为你需要做基于列的切片(在 CSR 格式中一定会很慢)。如果你经常这样做,CSR 可能不是一个好的选择,也许使用 CSC 代替,例如stackoverflow.com/questions/13352280/…
  • 来自文档:Disadvantages of the CSR format slow column slicing operations (consider CSC)sparse 的常见做法是在行动之前将矩阵转换为最佳类型。
  • 在一些快速测试中,X[I,:]X[:,I] 快大约 10 倍 csr 矩阵。 X.tocsc[:,I]X[:,I] 快一点。因此,如果您要进行大量列切片,则值得额外执行转换为 csc 格式的步骤。

标签: python numpy matrix scipy sparse-matrix


【解决方案1】:

您可以使用精美的索引来获取新的csr_matrix,其中包含您列表中的列:

all_cols = np.arange(old_m.shape[1])
cols_to_keep = np.where(np.logical_not(np.in1d(all_cols, cols_to_delete)))[0]
m = old_m[:, cols_to_keep]

【讨论】:

  • 如果您有大量列,则显式生成所有列索引并不理想
  • @ali_m 感谢您的反馈。我想不出更好的方法。你有什么想法吗?
【解决方案2】:

如果您有大量列,则生成完整的列索引集可能会变得相当昂贵。一种稍快的替代方法是暂时转换为COO format

import numpy as np
from scipy import sparse

def dropcols_fancy(M, idx_to_drop):
    idx_to_drop = np.unique(idx_to_drop)
    keep = ~np.in1d(np.arange(M.shape[1]), idx_to_drop, assume_unique=True)
    return M[:, np.where(keep)[0]]

def dropcols_coo(M, idx_to_drop):
    idx_to_drop = np.unique(idx_to_drop)
    C = M.tocoo()
    keep = ~np.in1d(C.col, idx_to_drop)
    C.data, C.row, C.col = C.data[keep], C.row[keep], C.col[keep]
    C.col -= idx_to_drop.searchsorted(C.col)    # decrement column indices
    C._shape = (C.shape[0], C.shape[1] - len(idx_to_drop))
    return C.tocsr()

检查等价性:

m, n, d = 1000, 2000, 20

M = sparse.rand(m, n, format='csr')
idx_to_drop = np.random.randint(0, n, d)

M_drop1 = dropcols_fancy(M, idx_to_drop)
M_drop2 = dropcols_coo(M, idx_to_drop)

print(np.all(M_drop1.A == M_drop2.A))
# True

基准测试:

In [1]: m, n = 1000, 1000000

In [2]: %%timeit M = sparse.rand(m, n, format='csr')
   ...: dropcols_fancy(M, idx_to_drop)
   ...: 
1 loops, best of 3: 1.11 s per loop

In [3]: %%timeit M = sparse.rand(m, n, format='csr')
   ...: dropcols_coo(M, idx_to_drop)
   ...: 
1 loops, best of 3: 365 ms per loop

【讨论】:

  • 您可以使用searchsorted 代替greater_outer 以获得更快的速度。也可以打电话给unique(idx_to_drop) :-)
  • @morningsun 感谢您纠正我的错误,以及您的其他建议。使用searchsorted 减少列索引是对使用广播的重大改进,尤其是当idx_to_drop 很大时。我希望我自己能想到!
猜你喜欢
  • 2020-01-25
  • 1970-01-01
  • 2021-08-03
  • 2019-11-10
  • 2013-07-22
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多