2016-05-01 11 views
2

Ich versuche, eine Art Interpolationsalgorithmus zu implementieren. I ist eine N * 4-Matrix, die Indizes von umgebenden Punkten von N anderen Punkten enthält. Elemente in jeder Zeile von I dürfen jedoch nicht eindeutig sein, dh zwei oder mehr von ihnen können sich auf einen einzelnen Punkt beziehen. Ich möchte wissen, wie viele eindeutige Indizes in jeder Zeile verfügbar sind, und ich möchte es so schnell wie möglich tun, da N groß ist!Wie finde ich die Anzahl der einzigartigen Elemente in jeder Zeile einer Matrix?

Antwort

1

Nun, Mohsen's answer ist eine allgemeine Lösung für dieses Problem, aber arrayfun war zu langsam für mich. Also habe ich ein wenig mehr darüber nachgedacht und eine viel schnellere Lösung gefunden. Ich vergleiche alle Paare von Spalten und einen Zähler erhöhen, wenn sie gleich waren:

tic; 
S = zeros(N, 1, 'uint32'); 
Nu = S+4; % in my case most of point are surrounded by four different points 
for i=1:3 
    for j=(i+1):4 
     S = S + uint32(I(:, i)==I(:, j)); 
    end 
end 
% Nu(S==0) = 4; 
Nu(S==1) = 3; 
Nu((S==2)|(S==3)) = 2; % why? :) 
Nu(S==6) = 1; 
toc; 

Für N=189225, arrayfun 14.73s auf meinem PC nimmt aber Summierung dauert nur 0,04s.

Edit: Achten Sie auf eine unterschiedliche Anzahl von Spalten

Hier ist eine Modifikation des Codes oben. Jetzt können wir auch die Plätze der einzigartigen Werte in jeder Reihe haben! Dieser hat nicht das :) Problem und kann für höhere Anzahlen der Spalten benutzt werden. Immer noch 0,04s auf meinem PC für 189225 Reihen.

tic; 
uniq = true(N, 4); 
for i=1:3 
    for j=(i+1):4 
      uniq(I(:, i)==I(:, j), j) = false; 
    end 
end 
Nu = sum(uniq, 2); 
toc; 

Edit (2): Der Vergleich mit EBH ‚s answer

Nach einer Weile habe ich dies für ein anderes Problem benötigt, wo ich Anzahl der einzelnen Elemente in jeder Reihe von Matrizen mit einer unterschiedlichen Anzahl von Spalten gesucht . Also habe ich meinen Code mit EBH verglichen, um zu sehen, ob ihr Code schneller ist. Ich lief beide Codes auf Matrizen mit Reihen von 10K bis 100K und Spalten von 6 bis 60. Die Ergebnisse sind durchschnittlich verbrachte Zeit (in Sekunden) von 3 verschiedenen Läufen:

enter image description here

Ich teste diese in 2016a und es gab eine signifikante Verbesserung der Leistung von FOR-Schleifen in den neuesten Versionen von MATLAB. Möglicherweise müssen Sie es also selbst vergleichen, wenn Sie es in älteren Versionen ausführen möchten.

2

Sie müssen unique Funktion in jeder Zeile verwenden und die Elemente des Ergebnisses zählen:

arrayfun(@(x) numel(unique(I(x,:))), (1:size(I,1)).') 

Die Indexanordnung umgesetzt wird, so dass das Ergebnis ein Spaltenvektor ist.

+0

Würden Sie bitte meine Antwort überprüfen. mamnoon misham;) – saastn

+0

Wie bearbeite ich die obige Syntax, damit Nullen nicht als eindeutiges Element berücksichtigt werden? – Sade

+0

ändere 'unique (I (x, :)) 'in' setdiff (I (x, :), 0) ' –

1

Hier ist eine super schnelle Art und Weise, ohne Schleifen zu tun:

accumarray(repmat(1:size(I,1),1,size(I,2)).',I(:),[],@(x) numel(unique(x))) 

Dies wird Ihnen eine Vektorgröße N, wobei das Element anstelle k die Anzahl der eindeutigen Elemente in I(k,:) ist.