我有一个包含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
答案 0 :(得分:2)
b = any(A);
b(find(b == 0,1)) = 1;
A=A(:,b)
修正每条评论以匹配op
答案 1 :(得分:2)
一种方法是使用all
并搜索每列的所有行,以查看列中的每个元素是否等于0.我们使用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
将返回一个空数组,切片到一个空数组也将产生一个空数组。因此,最后一行代码中的删除步骤将无效,并且您保持与之前相同的矩阵。
如果维持约束使得您只在矩阵末尾看到零列并且它们不出现在有效数据之间,我们可以通过组合any
和{{1}来实现此目的使用逻辑索引:
all
我们构建一个掩码,其中第一部分由所有非零的列组成。在此上下文中,any
将查找非零的所有列。这应该在数据的最开始发生,从而构建掩模的前半部分。下一部分使用diff
来查找与我们之前看到的相同out = A(:,any(A,1) | diff([false all(A == 0, 1)]));
调用输出的数组组合的成对差异。我们假设第一列永远不会为非零(这是您的情况),因此填充第一个元素为all
后跟相同false
调用的数组将确定逻辑数组只有一个时间,返回的差异为非零,这是返回第一个零列的点。我们将掩码中的这个位置设置为真,以及所有其他非零位置,我们最终将子集放入矩阵中,从而实现结果。