我有一个矩阵
m =
2 2 1
3 2 1
0 4 1
0 4 1
5 4 1
0 5 2
1 2 2
1 3 2
1 4 2
1 1 3
0 2 3
0 3 4
0 3 4
可能是N x 3,其中N可能非常大。
我想找到第一列(1-13)中的索引,其中我有零,但只有在有重复的行或行是唯一的时候。我不想要第二列和第三列相同但第一列不是零的行。换句话说,如果第一列中存在零但其第二列和第三列中的对应数字与第一列中具有不同数字的另一数字相同,则忽略该零的索引。所以,在上面的例子中,我想只返回索引6,11,12,13。索引3,4不应该返回,因为它们违反了与该行(第2列和第3列)类似的行的规则但是第一列是不同的,我们可以在下面看到:
0 4 1
0 4 1
5 4 1
一个缓慢的解决方案是找到第一列为0 indm=m(:,1)==0
的行的索引,然后迭代矩阵的行,检查矩阵中是否存在任何其他行(m
)具有相同的第2和第3列但不同的第1列。如果此类情况不存在,则将该行的索引添加到程序返回的列表中。
但是,这种方法需要" for循环"翻过大矩阵。
答案 0 :(得分:3)
解决此问题的一种方法(假设如果有任何其他行具有相同的列2和3,则行是错误的)是找到所有不同的行,然后检查第一列是否在任何地方都相同。 / p>
%# uIdx is the same for sets of rows where m(i,2:3) is equal
[~,~,uIdx] = unique(m(:,2:3),'rows');
%# allZeros is true if all entries in the first column of m
%# corresponding to a set are the zero
allZeros = accumarray(uIdx,m(:,1),[],@(x)all(x==0));
%# a good row belongs to a set of rows from m(:,2:3)
%# where all corresponding entries in the first column are zeros
%# use allZeros(uIdx) to expand allZeros to size(m,1)
goodRowIndices = find(allZeros(uIdx) == true)
goodRowIndices =
6
11
12
13
答案 1 :(得分:2)
这是我的解决方案:
mm = m(:,1)==0;
imm = find(mm);
[mu,~, imu] = unique(m(mm,2:3),'rows','stable');
[~,ia] = setdiff(mu,m(~mm,2:3),'rows');
X = imm(ismember(imu,ia));
第3行提取以0开头的唯一行;第4行只保留不以0开头的行中出现的行,第5行返回要保留的行的索引。
不确定它是最有效的方式,因为它涉及两种类型。