【问题标题】:Merging two matrices of different dimension in Matlab?在Matlab中合并两个不同维度的矩阵?
【发布时间】:2015-07-08 17:19:30
【问题描述】:

我在 Matlab 中有两个矩阵 A 和 B。 A 的维度为mx6,例如

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

B 具有维度 nx6,例如

B=[  1     1     1     1   |  1     1;
     1     2     3     1   |  1     1]

我想合并A 和B 并按照以下步骤创建矩阵C,而不使用循环:

1) 考虑B(i,1:4);如果存在j 使得A(j,1:4) 等于B(i,1:4) [这最多可能发生在一个j] 然后C(i,:)=[B(i,1:4) A(j,5)+B(i,5) A(j,6)+B(i,6)]。为所有i=1,...,n 执行此操作。

2) 将C 的剩余行填入A 和B 中按照步骤1) 无法匹配的行。

在示例中

C=[  1     1     1     1   |  2     1;  %Step 1) above
   ------------------------------------
     1     1     1     2   |  1     0;  %Step 2) above
     1     1     1     3   |  1     0;  %firstly rows from A
     1     1     1     4   |  1     0;
     1     2     3     2   |  1     0;
     1     2     3     3   |  1     0;
     1     2     3     4   |  1     0; 
     1     2     3     1   |  1     1]  %lastly rows from B

我尝试使用循环:

%STEP 1
     for i=1:size(B,1)
            for j=1:size(A,1)
                if all(B(i,1:4)==A(j,1:4),2)
                   C(i,:)=[B(i,1:4) A(j,5)+B(i,5) A(j,6)+B(i,6)]
                end
            end
        end



 %STEP 2


  C=[ C; A(logical(1-ismember(A(:,1:4), B(:,1:4),'rows')),:)];
  C=[ C; B(logical(1-ismember(B(:,1:4), A(:,1:4),'rows')),:)]; 

【问题讨论】:

  • 您是否编写过代码来尝试这样做?你有什么问题?
  • 我没有指定我不想使用循环。我不知道如何在不使用循环的情况下回答这个问题。刚刚编辑!
  • 请贴出你目前写的代码。

标签: matlab


【解决方案1】:

使用unique 和accumarray 的组合非常容易。 unique 的工作原理是为您提供一个输出矩阵,其中删除了所有重复的条目。这在使用 A 和 B 时会很好地工作。

只需将A 和B 连接成一个合并矩阵,然后将unique 与前4 列一起使用,并为此截断矩阵的每一行分配一个唯一ID。 unique 的第三个输出将为您提供该 ID,如果您想知道哪个 ID 对应于哪一行,则来自 unique 的第一个输出,其中输出的每一行都为您提供它对应的 ID到。

您可以使用'rows' 和'stable' 标志来确保我们查看矩阵中的每一行而不是每个单独的元素,并且使用'stable' 标志,我们会根据遇到唯一的时间来分配ID从开始(顶部)到结束(底部)的行。如果您没有放置'stable' 标志,它会在内部对行进行排序,然后从该排序列表的顶部到底部分配ID。

如果你想达到你想要的输出,你必须使用'stable'。找到这些 ID 后,在第五列和第六列分别使用两次 accumarray 并应用单独的总和并将结果组合在一起。 accumarray 通过提供一组 ID 或键来工作,对于每个 ID/键,都有一个与此键关联的输出值。您将共享相同键的所有值分组,并对每个组执行某些操作。在我们的例子中,我们将应用accumarray 两次,其中第一组输出值来自第五列,第二组输出值来自第六列。 accumarray 的默认行为是sum属于同一组的所有值,这正是您想要的。

在我们的例子中,accumarray 的输出将是一个单列向量,其长度与在第一步中使用unique 生成的唯一 ID 的总数一样长。您分别对第五列和第六列执行此操作,然后要获得最终矩阵,只需将unique 的第一个输出以及两个accumarray 输出合并到一个矩阵中即可最终获得输出。

类似这样的:

%// Your data
A=[  1     1     1     1     1     0;
1     1     1     2     1     0;
1     1     1     3     1     0;
1     1     1     4     1     0;
1     2     3     2     1     0;
1     2     3     3     1     0;
1     2     3     4     1     0];
B=[  1     1     1     1     1     1;
1     2     3     1     1     1];

%// Solution
[cols,~,id] = unique([A(:,1:4); B(:,1:4)], 'rows', 'stable');
out = accumarray(id, [A(:,5); B(:,5)]);
out2 = accumarray(id, [A(:,6); B(:,6)]);
final = [cols out out2];

这是我们的输出:

final =

     1     1     1     1     2     1
     1     1     1     2     1     0
     1     1     1     3     1     0
     1     1     1     4     1     0
     1     2     3     2     1     0
     1     2     3     3     1     0
     1     2     3     4     1     0
     1     2     3     1     1     1

【讨论】:

    【解决方案2】:

    这是一个不使用循环的解决方案。但是,我不太确定这会比循环更快。

    ind = 1:size(B,1);
    
    [indA, indA_true] = ismember(A(:,1:4),B(:,1:4),'rows');
    
    indB = indA_true(find(indA_true));
    
    C = [A(indA,1:4), A(indA,5:6) + B((indB),5:6)];
    
    C = [C; A(~indA,:); B(~ismember(ind',indB,'rows'),:)];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 2013-08-17
      相关资源
      最近更新 更多