我在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
。为所有C
执行此操作。
2)将剩余的A
行填入B
和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
的行,这些行根据步骤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
答案 0 :(得分:2)
使用unique
和accumarray
的组合非常容易。 unique
通过为您提供输出矩阵来工作,其中删除了所有重复条目。在使用A
和B
时,这会很有效。
只需将A
和B
连接成一个统一矩阵,然后将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'),:)];