删除所有行条目全为零的列,除了第一次出现

Removing columns with all row entries of all zero except for the first occurrence

我有一个包含 3 行和许多列的大矩阵。我想删除除第一次出现以外所有行都为零的列。

例如,给定以下矩阵:

    1 1 0 0 0 0 0 0
A = 1 0 0 1 0 0 0 0
    1 0 1 1 0 0 0 0

因此将转换为:

    1 1 0 0 0 
A = 1 0 0 1 0 
    1 0 1 1 0 
 b = any(A);
 b(find(b == 0,1)) = 1;
 A=A(:,b)

根据评论修正以匹配操作

一种方法是使用 all and search along all rows for every column to see if every element in a column is equal to 0. We use find 来确定这些列的位置。一旦这样做,就复制原始矩阵,然后转储所有具有零的列,除了我们第一次遇到这样的列:

ind = find(all(A == 0, 1));
out = A;
out(:,ind(2:end)) = [];

根据您的示例,我们得到:

>> out
out =
     1     1     0     0     0
     1     0     0     1     0
     1     0     1     1     0

这种方法的一个好处是,即使没有完全为零的列,find 也会 return 一个空数组,并且切入一个空数组也会产生一个空数组。因此,最后一行代码的删除步骤将不起作用,您将保持与之前相同的矩阵。


如果保持约束,您只会在矩阵的末尾看到零列,并且它们不会出现在有效数据之间,我们可以通过组合 anyall 逻辑索引:

out = A(:,any(A,1) | diff([false all(A == 0, 1)]));

我们构建了一个掩码,其中它的第一部分由所有非零列组成。 any in this context will find all columns that are non-zero. This should happen at the very beginning of your data thus building the first half of the mask. The next part uses diff 结合我们之前看到的相同 all 调用输出的数组来查找成对差异。我们假设第一列永远不会是非零的(这是你的情况),因此填充一个数组,其中第一个元素是 false 后跟相同的 all 调用将确定一个逻辑数组只有 一次 差值 returned 不为零,即第一个零列 returned 的点。我们将掩码中的这个位置以及所有其他非零位置设置为真,最后我们将子集放入您的矩阵中,从而实现您的结果。