在matlab中合并两个矩阵

时间:2017-02-08 10:05:14

标签: matlab search matrix

我有两个矩阵。一个是1,000,000 x 9,另一个是500,000 x 9。

列具有相同的含义,前7列具有键的功能。相应地,最后两列具有数据字符。两个矩阵中都有许多重叠键值,我希望有一个大矩阵来比较这些值。这个大矩阵的尺寸应为1,000,000 x 11。

例如:

A = [0 0 0 0 0 0 0 10 20; 0 0 0 0 0 0 1 30 40];
B = [0 0 0 0 0 0 0 50 60];

合并矩阵如下所示:

C = [0 0 0 0 0 0 0 10 20 50 60; 0 0 0 0 0 0 1 30 40 0 0];

如您所见,C的第一行包含来自矩阵A的第8列和来自矩阵B的第10,1列。第二行使用来自矩阵A的列8,9和用于最后一行的0,0列,因为矩阵B中没有相应的条目。

我从理论上完成了这项任务,但它非常非常慢。我经常使用循环。在任何其他编程语言中,我会对两个表进行排序,将在一个大循环中迭代两个表,保留两个指针。

Matlab中是否有更高效的算法可以使用矢量化,或者至少是足够有效的惯用/短期算法?

(补充说明:我最大的问题似乎是搜索功能:给定我的矩阵,我想抛出一个列向量7x1,让它命名为key来找到相应的行。现在,我使用bsxfun:

targetRow = data( min(bsxfun(@eq, data(:, 1:7), key), [], 2) == 1, :);

我使用min因为bsxfun的结果是一个带有7个匹配标志的向量,我显然希望它们都是真的。在我看来,这可能是Matlab算法的瓶颈)

2 个答案:

答案 0 :(得分:2)

可能使用ismember和一些索引:

% locates in B the last ocurrence of each key in A. idxA has logicals of
% those keys found, and idxB tells us where in B.
[idxA, idxB] = ismember(A(:,1:7), B(:,1:7),'rows'); 
C = [ A zeros(size(A, 1), 2) ];
C(idxA, 10:11) = B(idxB(idxA), 8:9); % idxB(idxA) are the idxB != 0

答案 1 :(得分:1)

我认为这可以做你想要的,只用你的简单例子进行测试。

% Initial matrices
A = [0 0 0 0 0 0 0 10 20;
     0 0 0 0 0 0 1 30 40];
B = [0 0 0 0 0 0 0 50 60];

% Stack matrices with common key columns, 8&9 or 10&11 for data columns
C = [[A, zeros(size(A,1),2)]; [B(:,1:7), zeros(size(B,1),2), B(:,8:9)]];
% Sort C so that matching key rows will be consecutive
C = sortrows(C,1:7);

% Loop through rows
curRow = 1;
lastRow = size(C,1) - 1;
while curRow < lastRow
    if all(C(curRow,1:7) == C(curRow+1,1:7))
        % If first 7 cols of 2 rows match, take max values (override 0s)
        % It may be safer to initialise the 0 columns to NaNs, as max will
        % choose a numeric value over NaN, and it allows your data to be
        % negative values.
        C(curRow,8:11) = max(C(curRow:curRow+1, 8:11));
        % Remove merged row
        C(curRow+1,:) = [];
        % Decrease size counter for matrix
        lastRow = lastRow - 1;
    else
        % Increase row counter
        curRow = curRow + 1;        
    end
end

答案:

C = [0     0     0     0     0     0     0    10    20    50    60
     0     0     0     0     0     0     1    30    40     0     0]