2011-07-22 7 views
1

Je suis confronté à un problème dans les éléments correspondants dans 2 matrices. Le premier élément peut être apparié en utilisant ismember mais le second élément doit être dans une plage. S'il vous plaît voir l'exemple ci-dessous:correspondance ID + trouver un nombre dans une matrice dans Matlab

% col1 is integerID, col2 is a number.  -->col1 is Countrycode, col2 is date 
bigmat = [ 600 2 
      600 4 
      800 1 
      800 5 
      900 1] ; 

% col1 is integerID, col2 is VALUE, col2 is a range -->value is Exchange rate 
datamat = {... 
      50 0.1 [2 3 4 5 6]  % 2:6 
      50 0.2 [9 10 11]   % 9:11 
      600 0.01 [1 2 3 4]   % 1:4 
      600 0.2 [8 9 10]   % 8:10 
      800 0.12 [1]    % 1:1 
      800 0.13 [3 4]    % 3:4 
      900 0.15 [1 2]  } ; % 1:2 

I need the answer as: 
    ansmat = [ 600 2 0.01 
       600 4 0.01 
       800 1 0.12 
       800 5 nan    % even deleting this row is fine 
       930 1 0.15 ] ; 

Pour simplifier:

  1. Tous les intIDs de matrix_1 existent dans matrix_2.
  2. Les chiffres de la plage sont des dates! Dans une plage, ces nombres sont consécutifs: [1 2 ... 5]
  3. Pour tout ID, les dates de la ligne suivante ne sont pas continues. Par exemple, vous pouvez voir [1 2 3 4] puis [8 9 10] dans la rangée suivante.

bigmat est une énorme matrice! 300,000-500,000 lignes et donc un code vectorisé serait apprécié. datamat est d'environ 5000 lignes ou moins. Vous pouvez convertir la cellule en matrice. Pour chaque rangée, j'ai le minimum et le maximum. La colonne 3 est minimum: maximum. Merci!

Répondre

0

Voici une implémentation possible:

%# data matrices 
q = [ 
    600 2 
    600 4 
    800 1 
    800 5 
    900 1 
]; 
M = { 
    50 0.1 [2 3 4 5 6] 
    50 0.2 [9 10 11] 
    600 0.01 [1 2 3 4] 
    600 0.2 [8 9 10] 
    800 0.12 [1] 
    800 0.13 [3 4] 
    900 0.15 [1 2] 
}; 

%# build matrix: ID,value,minDate,maxDate 
M = [cell2num(M(:,1:2)) cellfun(@min,M(:,3)) cellfun(@max,M(:,3))]; 

%# preallocate result 
R = zeros(size(M,1),3); 

%# find matching rows 
c = 1;    %# counter 
for i=1:size(q,1) 
    %# rows indices matching ID 
    ind = find(ismember(M(:,1),q(i,:))); 

    %# out of those, keep only those where date number is in range 
    ind = ind(M(ind,3) <= q(i,2) & q(i,2) <= M(ind,4)); 

    %# check if any 
    num = numel(ind); 
    if num==0, continue, end 

    %# extract matching rows 
    R(c:c+num-1,:) = [M(ind,1) repmat(q(i,2),[num 1]) M(ind,2)]; 
    c = c + num; 
end 

%# remove excess 
R(c:end,:) = []; 

Le résultat comme prévu:

>> R 
R = 
      600   2   0.01 
      600   4   0.01 
      800   1   0.12 
      900   1   0.15 
+0

Merci Amro ..mais la boucle For prend beaucoup de temps. J'essaie de voir si je peux utiliser une approche vectorisée. Pour la troisième colonne de datamat, j'ai déjà les valeurs minimum et maximum en tant que colonnes séparées. Je ne suis pas sûr de pouvoir les utiliser pour accélérer le code. Merci. – Maddy

+0

@Maddy: Ok vous avez raison, je l'ai juste testé avec des données aléatoires de la même taille que vous décrivez (300K et 5K), et cela a pris comme 70 secondes .. Aussi pour le min/max, vous pouvez directement les utiliser "M" à la place, mais je doute que cela fasse une énorme différence. Je vais essayer encore et voir si je peux améliorer le temps, donc restez à l'écoute;) – Amro

-1

Je ne suis pas tout à fait sûr que je comprends .. si la deuxième entrée est '600 4 0,02'?

Quoi qu'il en soit, vous pourrez peut-être essayer quelque chose comme:

% grab first column 
col = bigmat(:, 1); 

% find all entries in column that are equal to ID 
rel = (col == id); 

% retrieve just those rows 
rows = bigmat(rel, :); 

Ensuite, une fois que vous avez les lignes dont vous avez besoin de vos matrices, vous pouvez les concaténer ensemble comme ceci:

result = [rowsA(1:3) rowsB(2) rowsC(5:6)]; 
+0

Abe, 600 intID a une valeur de 0,01 pour [1 2 3 4] comme on peut le voir dans datamat. Un meilleur exemple est: 600 a 0,01 valeur pour les dates dites [734410 734411 734412 734413]. Merci pour votre réponse. – Maddy

Questions connexes