2016-05-05 9 views
2

Ich habe die Struktur Trajectories mit Feld uniqueDate, dateAll, Label: Ich möchte die Felder uniqueDate und dateAll vergleichen und, wenn es eine Korrespondenz gibt, ich werde in Label einen Wert von speichern eine andere Struktur.Beschleunigen Code zum Vergleichen von Feldern in einer Struktur

ich diesen Code geschrieben haben:

for k=1:nCols 
    for j=1:size(Trajectories(1,k).dateAll,1) 
     for i=1:size(Trajectories(1,k).uniqueDate,1) 
      if (~isempty(s(1,k).places))&&(Trajectories(1,k).dateAll(j,1)==Trajectories(1,k).uniqueDate(i,1))&&(Trajectories(1,k).dateAll(j,2)==Trajectories(1,k).uniqueDate(i,2))&&(Trajectories(1,k).dateAll(j,3)==Trajectories(1,k).uniqueDate(i,3)) 
       for z=1:24 
        if(Trajectories(1,k).dateAll(j,4)==z)&&(size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1)) 
         Trajectories(1,k).label(j)=s(1,k).places.all(z,i); 
        else if(Trajectories(1,k).dateAll(j,4)==z)&&(size(s(1,k).places.all,2)<size(Trajectories(1,k).uniqueDate,1)) 
          for l=1:size(s(1,k).places.all,2) 
           Trajectories(1,k).label(l)=s(1,k).places.all(z,l); 
          end 
         end 
        end 
       end 
      end 
     end 
    end 
end 

Z. B

Trajectories(1,4).dateAll=[1 2004 8 1 14 1 15 0 0 0 1 42 13 2;596 2004 8 1 16 20 14 0 0 0 1 29 12 NaN;674 2004 8 1 18 26 11 0 0 0 1 20 38 1;674 2004 8 2 10 7 40 0 0 0 14 26 5 3;674 2004 8 2 11 3 29 0 0 0 1 54 3 3;631 2004 8 2 11 57 56 0 0 0 0 30 8 2;1 2004 8 2 12 4 35 0 0 0 1 53 21 2;631 2004 8 2 12 52 58 0 0 0 0 20 36 2;631 2004 8 2 13 5 3 0 0 0 1 49 40 2;631 2004 8 2 14 0 20 0 0 0 1 56 12 2;631 2004 8 2 15 2 0 0 0 0 1 57 39 2;631 2004 8 2 16 1 4 0 0 0 1 55 53 2;1 2004 8 2 17 9 15 0 0 0 1 48 41 2]; 

Trajectories(1,4).uniqueDate= [2004 8 1;2004 8 2;2004 8 3;2004 8 4]; 

es läuft, aber es ist sehr, sehr langsam. Wie kann ich es ändern, um zu beschleunigen?

+1

Puuh, geben Sie uns vielleicht einen kleinen Satz von Eingabedaten (wenn möglich, indem Sie es aus MATLAB generieren, damit wir es uns leicht selbst versuchen können). Meine erste Idee wäre, das gesamte Datenlayout zu überdenken. Vielleicht wäre es einfacher, mehrere einzelne Matrizen anstelle einer großen Struktur zu verwenden. – tim

+0

http://stackoverflow.com/a/4169216/2399799 –

Antwort

1

Lassen Sie uns von innen nach außen arbeiten und sehen, wo es uns hinbringt.

Schritt 1: Vereinfachen Sie Ihre Vergleichsbedingung:

if (~isempty(s(1,k).places))&&(Trajectories(1,k).dateAll(j,1)==Trajectories(1,k).uniqueDate(i,1))&&(Trajectories(1,k).dateAll(j,2)==Trajectories(1,k).uniqueDate(i,2))&&(Trajectories(1,k).dateAll(j,3)==Trajectories(1,k).uniqueDate(i,3)) 

wird

if (~isempty(s(1,k).places)) && all(Trajectories(1,k).dateAll(j,1:3)==Trajectories(1,k).uniqueDate(i,1:3)) 

Dann wollen wir diese entfernen, von einer for-Schleife. Die „schneiden“ Funktion ist hier nützlich:

[ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows'); 

Wir haben jetzt eine Vektor i1 aller Zeilen in dateAll, die mit uniqueDate schneiden.

[iz iz1 iz2] = intersect(Trajectories(1,k).dateAll(i1,4),1:24); 

Wir müssen vorsichtig sein, über unseren Indizes hier, um eine Teilmenge einer Teilmenge mit:

Jetzt können wir die Schleife zu vergleichen z mit einem ähnlichen Ansatz entfernen.

Dies vereinfacht den Code:

for k=1:nCols 
    if isempty(s(1,k).places) 
     continue; % skip to the next value of k, no need to do the rest of the comparison 
    end 
    [ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows'); 
    [iz iz1 iz2] = intersect(Trajectories(1,k).dateAll(i1,4),1:24); 

    usescalarlabel = (size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1); 
    if (usescalarlabel) 
     Trajectories(1,k).label(i1(iz1)) = s(1,k).places.all(iz,i2(iz1)); 
    else 
     % you will need to check this: I think here you were needlessly repeating this step for every match 
     Trajectories(1,k).label(i1(iz1)) = s(1,k).places.all(iz,:); 
    end 
end 

Aber warten Sie! Diese z-Schleife entspricht genau der Indizierung. So brauchen wir nicht, dass die zweite intersect schließlich:

for k=1:nCols 
    if isempty(s(1,k).places) 
     continue; % skip to the next value of k, no need to do the rest of the comparison 
    end 
    [ia i1 i2]=intersect(Trajectories(1,k).dateAll(:,1:3),Trajectories(1,k).uniqueDate(:,1:3),'rows'); 

    usescalarlabel = (size(s(1,k).places.all,2)>=size(Trajectories(1,k).uniqueDate,1); 
    label_indices = Trajectories(1,k).dateAll(i1,4); 
    if (usescalarlabel) 
     Trajectories(1,k).label(label_indices) = s(1,k).places.all(label_indices,i2); 
    else 
     % you will need to check this: I think here you were needlessly repeating this step for every match 
     Trajectories(1,k).label(label_indices) = s(1,k).places.all(label_indices,:); 
    end 
end 

Sie müssen die Indizierung in dem überprüfen - ich bin sicher, dass ich irgendwo einen Fehler gemacht habe, ohne dass Daten, die gegen zu testen, aber das sollte Ihnen eine Idee geben, wie Sie die Schleifen entfernen und stattdessen Vektorausdrücke verwenden können. Ohne die Daten zu sehen, die ich so weit optimieren kann. Sie können möglicherweise weiter gehen, wenn Sie Ihre Daten in eine Reihe von 3D-Matrizen/Zellen formatieren können, anstatt Strukturen zu verwenden.

Ich bin misstrauisch gegenüber Ihrer Erkrankung, die ich "usescalarlabel" genannt habe - es scheint, als würden Sie zwei Datentypen mischen. Auch würde ich dringend empfehlen, die dateAll-Matrizen in separate "date" - und "data" -Matrizen zu trennen, da die Zeilenindizes 4 und 4 anscheinend keine Datumsangaben sind. Auch das Beispiel, das Sie kopieren/einfügen, scheint einen zusätzlichen Wert im Zeilenindex 1 zu haben? In diesem Fall müssen Sie Trajectories(1,k).dateAll(:,2:4) anstelle von Trajectories(1,k).dateAll(:,1:3) vergleichen.

Viel Glück.

Verwandte Themen