【问题标题】:How to find rows of a matrix where with the same ordering of unique and duplicated elements, but not necessarily the same value如何找到具有相同顺序的唯一元素和重复元素但不一定具有相同值的矩阵行
【发布时间】:2014-02-04 03:24:24
【问题描述】:

我不太确定如何表达这个问题。假设我有以下矩阵:

A=[1 0 0;
   0 0 1;
   0 1 0;
   0 1 1;
   0 1 2;
   3 4 4]

给定第 1 行,我想找到所有行:

  • 在第 1 行中唯一的元素,在另一行的同一列中是唯一的,但不一定具有相同的值
  • 如果第 1 行存在重复值的元素,则另一行的相同列中存在重复值,但不一定是相同值

例如,在矩阵 A 中,如果给定第 1 行,我想找到第 4 行和第 6 行。

【问题讨论】:

标签: algorithm matlab matrix


【解决方案1】:

目前无法对此进行测试,但我认为以下方法可行:

A=[1 0 0;
   0 0 1;
   0 1 0;
   0 1 1;
   0 1 2;
   3 4 4];

B = zeros(size(A));

for ii = 1:size(A,1)
  r = A(ii,:);
  B(ii,1) = 1;
  for jj = 2:size(A,2)
    c = find(r(1:jj-1)==r(jj));
    if numel(c) > 0
      B(ii,jj) = B(ii,c);
    else
      B(ii,jj) = B(ii,jj-1)+1;
    end
  end
end

最后,我们有一个数组 B,其中“相似的索引具有相似的值”,并且您要查找的行现在是相同的。

现在你可以做

[C, ia, ic] = unique(B,'rows','stable');
disp('The answer you want is ');
disp(ia);

而您想要的答案将在变量ia 中。见http://www.mathworks.com/help/matlab/ref/unique.html#btb0_8v。我不能 100% 确定您可以在同一个调用中使用 rowsstable 参数 - 但我认为您可以。

尝试一下,看看它是否有效 - 如果您需要更多信息,请提出问题。

【讨论】:

  • 更新 - 是打电话给unique(B,'rows','stable') - 不是A...这样更好吗?
【解决方案2】:

这是一个简单的方法

B = NaN(size(A)); %//Preallocation

for row = 1:size(A,1)
    [~,~,B(row,:)] = unique(A(row,:), 'stable');
end

find(ismember(B(2:end,:), B(1,:), 'rows')) + 1

【讨论】:

    【解决方案3】:

    没有循环的简单解决方案:

    row = 1; %// row used as reference
    equal = bsxfun(@eq, A, permute(A, [1 3 2]));
    equal = reshape(equal,size(A,1),[]); %// linearized signature of each row
    result = find(ismember(equal,equal(row,:),'rows')); %// find matching rows
    result = setdiff(result,row); %// remove reference row, if needed
    

    关键是计算每一行的“签名”,表示其元素的所有组合之间的相等关系。这是通过bsxfun 完成的。然后,使用ismember 可以轻松找到具有相同签名的行。

    【讨论】:

      【解决方案4】:

      谢谢,弗洛里斯。唯一调用无法正常工作,我认为您也打算在其中使用矩阵 B。这是我设法做的,虽然它不是那么干净:

      A=[1 0 0 1;
         0 0 1 3;
          0 1 0 1;
          0 1 1 0;
          0 1 2 2;
          3 4 4 3;
          5 9 9 4];
      
       B = zeros(size(A));
      
       for ii = 1:size(A,1) 
         r = A(ii,:); 
         B(ii,1) = 1; 
         for jj = 2:size(A,2) 
            c = find(r(1:jj-1)==r(jj)); 
           if numel(c) > 0 
             B(ii,jj) = B(ii,c);
           else
               B(ii,jj) = max(B(ii,:))+1; % need max to generalize to more columns
           end
         end
       end
      
       match = zeros(size(A,1)-1,size(A,2));
       for i=2:size(A,1)
           for j=1:size(A,2)
               if B(i,j) == B(1,j)
                   match(i-1,j)=1;
               end
           end
       end
      
       index=find(sum(match,2)==size(A,2));
      

      在嵌套循环中,我检查它下面的行中的元素是否在正确的列中匹配。如果存在完美匹配,则该行的总和应为行维度。

      当我针对特定问题进行概括时,我正在处理矩阵填充一组特定的基本大小(A,2)数字。因此,对于 base 4 和更大的值,在 else 语句中需要一个 max 语句以防止匹配。否则,对于给定行中的某些数字组合,当没有元素时,可能会出现重复元素。

      【讨论】:

        【解决方案5】:

        概述是将每一行减少为一个“签名”计数元素重复,即您的第 1 行变为 1、2。然后检查相等的签名。

        【讨论】:

        • 嗯,这或多或少是我所做的 :-) 另外,请注意像“1,2”这样的东西作为签名无效。例如,1 0 0 21 0 0 1 这样的行在结构不同时都会给出“1,2,1”签名
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多