在Matlab中合并两个不同维度的矩阵?

时间:2015-07-08 17:19:30

标签: matlab

我在Matlab中有两个矩阵AB。 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]

我想合并AB并按照这些步骤创建矩阵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。为所有C执行此操作。

2)将剩余的A行填入BC=[ 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 的行,这些行根据步骤1无法匹配。

在示例中

%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')),:)]; 

我尝试使用循环:

RecycleView

2 个答案:

答案 0 :(得分:2)

使用uniqueaccumarray的组合非常容易。 unique通过为您提供输出矩阵来工作,其中删除了所有重复条目。在使用AB时,这会很有效。

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

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

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

在我们的案例中,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

答案 1 :(得分:0)

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

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'),:)];