2015-06-16 2 views
0

Я пытаюсь объединить две матрицы, которые используют одни и те же значения в нескольких столбцах.Присоединить матрицы с одинаковыми значениями в разных векторах в MATLAB

Следующие матрицы должны служить примером моей проблемы и предоставить MWE. Тем не менее, мои данные очень длинны size(500000, 4), поэтому я ищу эффективный способ их слияния. Данные состоят из опционных данных, где c являются вызовами и p помещают данные, со столбцами 1:4: дата, забастовка, истечение, цена предложения. В конце концов, я хотел бы иметь матрицу с колонками 1:5: дата, забастовка, истечение срока, цена bid-bid, цена bid-bid. Как показано в MWE, данные не имеют одинаковой длины, но каждая комбинация столбцов 1:3 (дата, забастовка, истечение срока действия) существует только один раз.

c = [7356011 300 7356081 1.15; 7356011 400 7356081 1.56; 7356011 500 7356081 1.79; 7356011 300 7356088 1.25; 7356011 400 7356088 1.67; 7356011 500 7356088 1.89; 7356011 600 7356088 1.92; 7356012 300 7356081 0.79; 7356012 400 7356081 0.99; 7356012 500 7356081 1.08; 7356012 300 7356088 0.81; 7356012 400 7356088 0.90; 7356012 500 7356088 1.07]

p = [7356011 300 7356081 1.35; 7356011 400 7356081 1.15; 7356011 500 7356081 1.03; 7356011 300 7356088 1.56; 7356011 400 7356088 1.15; 7356011 500 7356088 1.03; 7356012 300 7356081 1.25; 7356012 400 7356081 1.19; 7356012 500 7356081 1.02; 7356012 300 7356088 1.14; 7356012 400 7356088 0.98; 7356012 500 7356088 0.76; 7356012 600 7356088 0.56; 7356012 700 7356088 0.44]

Я пытался построить идентификатор для каждого столбца, с помощью strcat и num2str, а также получение «идентификатор (1) = 73560113007356081», однако это занимает очень много времени для большого количества данные. Я также пытался найти решение, используя unique и ismember, но имел проблемы с несколькими столбцами.

Хотела выход будет:

7356011 300 7356081 1.15 1.35 7356011 400 7356081 1.56 1.15 7356011 500 7356081 1.79 1.03 7356011 300 7356088 1.25 1.56 7356011 400 7356088 1.67 1.15 7356011 500 7356088 1.89 1.03 7356011 600 7356088 1.92 NaN 7356012 300 7356081 0.79 1.25 7356012 400 7356081 0.99 1.19 7356012 500 7356081 1.08 1.02 7356012 300 7356088 0.81 1.14 7356012 400 7356088 0.90 0.98 7356012 500 7356088 1.07 0.76 7356012 600 7356088 NaN 0.56 7356012 700 7356088 NaN 0.44

Спасибо за любую помощь

+0

Почему ваша искомая матрица имеет NaNs? – SamuelNLP

+0

получил это, неважно. – SamuelNLP

ответ

1

Вам не нужно использовать петлю, вместо этого используйте intersect.

[~,ic,ip] = intersect(c(:, 1:3),p(:, 1:3),'rows'); 
m = [c(ic, :), p(ip,end)]; 

Edit: Если вы хотите включить NaN S, где они не пересекаются, как над плакатом.

function m = merge(c, p, nc, np) 
    %check for input arg errors 
    if nargin == 3 
     np = nc; 
    elseif nargin ~= 4 
     disp('Please enter either 3 or 4 arguments') 
     m = {}; 
     return 
    end 

    %make sure they are shaped the same 
    nc = reshape(nc, 1, []); 
    np = reshape(np, 1, []); 

    %And have the same number of elements 
    if numel(nc) ~= numel(np) 
     disp('Please ensure arguments 3 and 4 have the same number of elements') 
     m = {}; 
     return 
    end 

    %The columns that aren't being compared 
    NotNC = find(~ismember(1:size(c,2), nc)); 
    NotNP = find(~ismember(1:size(p,2), np)); 

    %Find the matching rows 
    [matches,ic,ip] = intersect(c(:, nc),p(:, np),'rows'); 

    %Put together matching rows with the other data not included in the match 
    m1 = [matches, c(ic, NotNC), p(ip, NotNP)]; 

    %Find rows that did not matched 
    NotIC = find(~ismember(1:size(c,1), ic)); 
    NotIP = find(~ismember(1:size(p,1), ip)); 

    %Put together data not in the matched set 
    m2 = [c(NotIC, nc), c(NotIC, NotNC), nan(length(NotIC), size(NotNP,2))]; 
    m3 = [p(NotIP, np), nan(length(NotIP), size(NotNC,2)), p(NotIP, NotNP)]; 

    %merge all three lists 
    m = [m1; m2; m3]; 

end 
+0

Это значительно быстрее, чем сообщение Сэмюэля. 'tic; слияние (a, b, 1: 3); toc ', ' Прошло время: 0.048150 секунд. ' 'tic; Самуил (a, b); toc ' ' Истекшее время 8.432094 секунды. ' – user1543042

+0

Спасибо большое! Также к @SamuelNLP Работало также отлично, однако из-за количества данных, которые я предпочитаю выше решения! – philippe

0

Ok, я не понимаю, если р всегда больше, так что я буду писать два решения с if.

if length(c) > length(p) 
    xx = length(c); 
    newm = [c NaN(xx, 1)]; 
    row = ismember(c, p, 'rows'); 

    newm(row, end) = p(row, end); 
else 
    xx = length(p); 
    newm = [p(:,1:3) NaN(xx, 1) p(:, end)]; 

    row = ismember(p(:,1:3), c(:,1:3), 'rows'); 

    newm(row, 4) = c(row, end); 
end 

UPDATE:

этот код работает для данного примера.

[row_p, row_c] = ismember(p(:,1:3), c(:,1:3), 'rows'); 

newm = []; 

for ii = 1:length(row_p) 
    if row_p(ii) == 1 
     newm = [newm; p(ii, 1:3) c(row_c(ii), end) p(ii, end)]; 
    else 
     newm = [newm; p(ii, 1:3) NaN p(ii, end)]; 
    end 
end 

[row_c, row_p] = ismember(c(:,1:3), p(:,1:3), 'rows'); 

for ii = 1:length(row_c) 
    if row_c(ii) == 1 
     newm = [newm; c(ii, 1:3) c(ii, end) p(row_p(ii), end)]; 
    else 
     newm = [newm; c(ii, 1:3) c(ii, end) NaN]; 
    end 
end 

newm = unique(newm, 'rows'); 
+0

Произошла небольшая ошибка, исправлена. – SamuelNLP

+0

Большое спасибо. Оператор 'if' велик, поскольку матрицы' c' и 'p' иногда отличаются по длине Однако, как я могу решить эту проблему, если у меня есть строка в' c', которая не находится в 'p' и наоборот. Я отредактировал этот пример, чтобы показать, что я имею в виду. Поскольку теперь невозможно выбрать матрицу в качестве базовой матрицы, которая заполняется другой. Заранее спасибо – philippe

+0

Вы уверены, что '7356012 700 7356088 NaN 0.44' должен быть последним рядом? – SamuelNLP

Смежные вопросы