2015-07-08 3 views
4

У меня есть две матрицы A и B в Matlab. А имеет размер mx6, например.Слияние двух матриц разного размера в Matlab?

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

Вы писали код, чтобы попытаться это сделать? Какая у вас проблема? – rlbond

+0

Я не указал, что я не хочу использовать циклы. Я понятия не имею, как ответить на вопрос, не используя циклы. Просто отредактирован! – user3285148

+0

Пожалуйста, напишите код, который вы написали. – rlbond

ответ

2

Это довольно легко, используя комбинацию unique и accumarray. unique работает, предоставляя вам матрицу вывода, в которой удаляются все дубликаты записей. Это будет хорошо работать, когда дело доходит до игры с A и B.

Просто конкатенации A и B вместе в единые сводные матрицы, а затем использовать unique с первыми 4 столбцов и назначить каждую строку этой усеченной матрицы уникального идентификатора. Третий вывод unique даст вам этот идентификатор, и если вы хотите узнать, какой идентификатор соответствует той строке, которая выводится из первого вывода unique, где каждая строка выводит идентификатор, который соответствует.

Вы бы использовать флаг 'rows' и 'stable', чтобы гарантировать, что мы смотрим на каждой строке, а не каждого отдельного элемента в матрице и с 'stable' флагом, мы назначаем идентификаторы на основе, когда мы сталкиваемся с уникальной строки с самого начала (сверху) до финиша (снизу). Если вы не поместили флаг 'stable', введите строки внутри, а затем присвойте идентификаторы, начиная с верхней части этого списка.

Если вы хотите достичь желаемого результата, вы должны использовать 'stable'. Когда вы найдете эти идентификаторы, используйте accumarray дважды на пятом и шестом столбцах соответственно и примените отдельную сумму и объедините результаты вместе. accumarray работает, предоставляя набор идентификаторов или ключей, а для каждого ID/ключа есть выходное значение, связанное с этим ключом. Вы группируете все значения, которые используют один и тот же ключ, и делайте что-то для каждой группы.В нашем случае мы будем применять accumarray дважды, где первый набор выходных значений поступает из пятого столбца, а второй набор выходных значений поступает из шестого столбца. Поведение по умолчанию с accumarray - это сумма все значения, принадлежащие к той же группе, которые вы хотели.

В нашем случае выход accumarray будет представлять собой один вектор-столбец, равный общему количеству уникальных идентификаторов, сгенерированных на первом этапе, с unique. Вы делаете это для пятого и шестого столбцов отдельно, а затем для получения своей окончательной матрицы просто объедините первый вывод 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 
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'),:)]; 
Смежные вопросы