【问题标题】:Efficiently test matrix rows and columns with numpy使用 numpy 有效地测试矩阵行和列
【发布时间】:2018-03-28 05:34:41
【问题描述】:

当第 i 行 i 列都包含全 0 时,我正在尝试删除第 i 行和第 i 列。例如,在这种情况下,我们可以看到第 0 行全为零,第 0 列全为零,因此删除了第 0 行和第 0 列。与第 2 行和第 4 行列对相同。第 1 行全为零,但第 1 列不是,因此两者都不会被删除。

[0,0,0,0,0]
[0,1,0,1,0]
[0,0,0,0,0]
[0,0,0,0,0]
[0,0,0,0,0]

会变成

[1,1]
[0,0]

另一个例子:

[0,0,1,0,0,1]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,1,0,1,0]

将更改为:

[0,1,0,1]
[0,0,0,0]
[0,0,0,0]
[0,1,1,0]

这是我用来计算的代码:

def remove(matrix):
    for i, x in reversed(list(enumerate(matrix))):
        if np.all(matrix == 0, axis=0)[i] and np.all(matrix == 0, axis=1)[i]:
            matrix = np.delete(matrix,i,axis=0)
            matrix = np.delete(matrix,i,axis=1)
    return matrix

经过测试,这条线目前花费的时间最多:

if np.all(matrix == 0, axis=0)[i] and np.all(matrix == 0, axis=1)[i]:

有没有更合适的方式来以这种方式测试行和列?我使用的矩阵是一个稀疏的二进制矩阵。我没有使用任何稀疏矩阵类,只是 ndarray。

【问题讨论】:

  • 不-一开始我也是这么想的,但我相信原始问题想在两者都为零时同时删除列和行。
  • 从 OP 的例子来看,我相信是这样。交叉的行和列索引当然必须匹配。
  • 是的,这就是我的意思,很抱歉造成混乱。
  • @RamseyBissex 请使用正确的预期输出编辑问题。此外,如果可能,请使用更大/更通用的示例案例并向我们展示预期的输出。
  • 我们现在应该修复了,感谢您的耐心等待。

标签: python performance numpy matrix sparse-matrix


【解决方案1】:

带有掩码的矢量化方法 -

def remove_vectorized(a):
    mask = a==0
    m_row = ~mask.all(1)
    m_col = ~mask.all(0)
    comb_mask = m_row | m_col
    return a[comb_mask][:,comb_mask] #or a[np.ix_(comb_mask, comb_mask)]

样本运行

案例#1:

In [485]: a
Out[485]: 
array([[0, 0, 0, 0, 0],
       [0, 1, 0, 1, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])

In [486]: remove_vectorized(a)
Out[486]: 
array([[1, 1],
       [0, 0]])

案例#2:

In [489]: a
Out[489]: 
array([[0, 0, 1, 0, 0, 1],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 0]])

In [490]: remove_vectorized(a)
Out[490]: 
array([[0, 1, 0, 1],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 1, 1, 0]])

【讨论】:

  • 我不相信这回答了最初的问题。但是,这将删除所有为零的行或列-我认为发布者想要的是删除 both 同时为 0 的行 列。在 np.ix_() 中使用位掩码之前,您可以通过将位掩码相互连接来修复您的帖子。
【解决方案2】:

您可以做的一件事是在 for 循环之外评估布尔矩阵“matrix == 0”,并使用该矩阵而不是每次运行都重新评估它。

应该是这样的:

def remove(matrix):
    binary_matrix = matrix == 0
    for i, x in reversed(list(enumerate(matrix))):
        if np.all(binary_matrix , axis=0)[i] and np.all(binary_matrix , axis=1)[i]:
            matrix = np.delete(matrix,i,axis=0)
            matrix = np.delete(matrix,i,axis=1)
            binary_matrix = np.delete(binary_matrix ,i,axis=0)
            binary_matrix = np.delete(binary_matrix ,i,axis=1)
    return matrix

【讨论】:

    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    相关资源
    最近更新 更多