【问题标题】:Find set intersection of multiple arrays in MATLAB在MATLAB中查找多个数组的集合交集
【发布时间】:2012-12-29 08:59:00
【问题描述】:

我试图解决这个问题,但我无法实现。 你能帮我做点什么吗?

问题

Mat1 | Mat2 | Mat3

 1 2 | 1 3  | 2 6

 1 3 | 2 6  | 2 5

 2 4 | 3 1  | 3 1

 3 1 | 3 5  | 5 2

 4 5 |

当有 3 个矩阵时(例如上面的例子),我想在[column1 column2 matrixnumber] 形式的交集行中得到这个结果。

上面例子的结果是

1 3 1

1 3 2

2 6 2

2 6 3

3 1 1

3 1 2

3 1 3

如果结果是[column1 column2 firstmatrix secondmatrix, ...]的形式就可以了

1 3 1 2

2 6 2 3

3 1 1 2 3

对于这个问题,我想最多使用一个for循环。

你对此有什么想法吗?

【问题讨论】:

  • 只是为了确定:如果一对出现在所有三个矩阵上,您想查看什么?所有三个成对出现?

标签: matlab rows intersection


【解决方案1】:

这里是使用 MATLAB 的intersect 的替代解决方案(似乎比 Gunther 的运行速度更快):

Mat = {[1 2; 1 3; 2 4; 3 1; 4 5],
       [1 3; 2 6; 3 1; 3 5],
       [2 6; 2 5; 3 1; 5 2]};

result = zeros(sum(cellfun(@(x)size(x, 1), Mat)), 3); % # Preallocate memory
k = 1;
for cc = transpose(nchoosek(1:numel(Mat), 2))
    x = intersect(Mat{cc}, 'rows');                   % # Find intersection
    y = ones(size(x, 1), 2) * diag(cc);               % # Generate matrix indices
    result(k:k + numel(y) - 1, :) = [[x; x], y(:)];
    k = k + numel(y);
end

result(all(~result, 2), :) = [];                      % # Discard zero rows
result = unique(result, 'rows');                      % # Discard repeated rows

矩阵result 现在应该包含唯一的交集行及其对应的矩阵索引,就像您想要的那样:

result =   
     1     3     1
     1     3     2
     2     6     2
     2     6     3
     3     1     1
     3     1     2
     3     1     3

【讨论】:

    【解决方案2】:

    如果我理解正确,您有许多对:Mat1,Mat2,Mat3,...MatN。现在您想找到唯一对,然后找出每个唯一对出现在哪个集合中。

    如果你有大量的集合,我建议你开始使用cell array 来保存它们,让事情变得更容易:

    N = 3; % total number of data sets
    Mat = cell(N,1);
    Mat{1} = [1 2;
              1 3;
              2 4;
              3 1;
              4 5];
    Mat{2} = [1 3;
              2 6;
              3 1;
              3 5];
    Mat{3} = [2 6;
              2 5;
              3 1;
              5 2];
    % etc.
    

    首先让我们找到唯一的对:

    uniq_pairs = unique(cat(1,Mat{:}),'rows');
    M = size(uniq_pairs ,1);
    

    然后使用ismember 检查哪些集合包含哪些对:

    matcontpair = false(M,N); %preallocate
    for ii=1:N % unavoidable loop
        matcontpair(:,ii) = ismember(uniq_pairs,Mat{ii},'rows');
    end
    

    要将此交集矩阵转换为每对的一组矩阵数字,请再次循环遍历它并将最终结果存储在元胞数组中(您不能使用数组,因为它们的大小可能不同(有些对只找到一次,其他两次,其他三次...)

    pair_occurence= cell(M,1);
    d=1:N;
    for jj=1:M
        pair_occurence{jj} = d(matcontpair(jj,:));
    end
    

    现在您有一个大小为 Mx2 的矩阵 uniq_pairs 包含唯一对,以及一个大小为 Mx1 的出现单元数组 pair_occurence:每个单元对应于一对并包含一个矩阵列表,其中该对存在。

    如果要从列表中删除仅存在于一个矩阵中的对,请使用以下命令:

    % find them
    lonely_pairs = cellfun(@numel,pair_occurence)<2;
    % and destroy them
    uniq_pairs(lonely_pairs,:) = [];
    pair_occurence(lonely_pairs) = [];
    

    【讨论】:

    • 感谢您的回复。当我检查解决方案时,for 循环中的唯一行和 ismember 函数可能需要一些时间。如果行数很大,则行的“唯一”需要很长时间。 for循环中的'ismember'函数意味着它搜索每一行的所有矩阵,因此可能需要一些时间(O(唯一行数*所有行数)。你认为你的解决方案是优化的吗?跨度>
    • 您确实想找到每个矩阵中的每一行,不是吗?试试@EitanT 的解决方案,如果有很多独特的行,那应该会更快。
    • @GuntherStruyf 感谢您的支持!
    • 感谢您的支持,@GuntherStruyf
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多