WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Werte zählen in einer Zx2 Matrix

 

Paul222

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 21.10.2010, 11:48     Titel: Werte zählen in einer Zx2 Matrix
  Antworten mit Zitat      
Hallo Leute,

ich steh da vor einem kleinen Problem zu dem mir keine Lösung einfällt. Ich hab eine Matrix der Dimension 1600x2. Die Einträge entsprechen Koordinaten von Punkten (Spalte1 = X-Koordinate, Spalte2 = Y-Koordinate, Zeilen entsprechen den einzelnen Punkten).
Ich würde nun gerne zählen, wie oft der selbe Punkt vorkommt. Die Ausgabe sollte so aussehen, dass eine Zx3 Matrix entsteht, in der wieder in Spalte1 die X-Koordinate, in Spalte 2 die Y-Koordinate und in Spalte 3 die Anzahl dieses Punktes steht.

Hat jemand eine Idee, wie man das machen könnte?

Vielen Dank
LG Paul


Sco
Forum-Meister

Forum-Meister


Beiträge: 699
Anmeldedatum: 15.08.10
Wohnort: Dundee
Version: 2008a, 2010a
     Beitrag Verfasst am: 21.10.2010, 13:21     Titel:
  Antworten mit Zitat      
Hallo Paul,

das wuerde z.B. so funktionieren:
Code:

test = [1.2 1.3;2.3 2.4;1.2 1.3;3 1;3 2;1.2 1.3;1 3;4 5;4 5; 8.456 0; 8.456 0];

for k = 1:size(test,1)
   temp = bsxfun(@eq,test,test(k,:));
   test(k,3) = nnz(and(temp(:,1),temp(:,2)));
end
 


Vielleicht weiss ja noch jemand wie man noch die for-Schleife wegbekommt?

MFG

Sco
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 21.10.2010, 16:48     Titel:
  Antworten mit Zitat      
Hallo

auf eine FOR-Schleife kann hier nicht verzichten:

Code:

v = [1.2 1.3;2.3 2.4;1.2 1.3;3 1;3 2;1.2 1.3;1 3;4 5;4 5; 8.456 0; 8.456 0];
u = unique(v,'rows')
[dummy,pos]=ismember(v,u,'rows')

anz = zeros(size(u,1),1)
for k=1:size(u,1)
 anz(k)=sum(pos==k)
end

res= [u,anz]
 


@Sco du hast 2 Schleifen. BSXFUN gehört zu der versteckten Schleifen
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 21.10.2010, 22:53     Titel:
  Antworten mit Zitat      
Hallo Denny,

Code:

[ ... ]
u = unique(v,'rows')
[dummy,pos]=ismember(v,u,'rows')
[ ... ]
 

UNIQUE und ISMEMBER beinhalten neben den versteckten Schleifen auch noch zwei Sortierungen. Deswegen könnte man das deutlich beschleunigen, wenn man aus den beiden Spalten für X- und Y-Koordinaten eine einizge erzeugen könnte. Dann wäre HISTC anwendbar, man bräucht für die Edge-Werte aber doch UNIQUE.

Wenn X und Y z.B. ganzzahlig ist und zwischen 0 und 255 liegt, wäre X*256+Y hilfreich. Aber eine allgemeine Lösung gibt es da nicht und für Floatingpoint-Zahlen ist das Problem der Rundungsfehler sehr hinderlich.

Folglich wäre dies ein idealer Kandidat für ein C-Mex-Programm, wenn es denn wirklich zeitkritisch ist.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 22.10.2010, 14:29     Titel:
  Antworten mit Zitat      
Jan S hat Folgendes geschrieben:
Hallo Denny,

UNIQUE und ISMEMBER beinhalten neben den versteckten Schleifen auch noch zwei Sortierungen. Deswegen könnte man das deutlich beschleunigen, wenn man aus den beiden Spalten für X- und Y-Koordinaten eine einizge erzeugen könnte. Dann wäre HISTC anwendbar, man bräucht für die Edge-Werte aber doch UNIQUE.
Gruß, Jan

Und? Ich habe diese aber nicht verschachtelt. ISMEMBER ist auf Zahlen sehr schnell, Schleifen braucht es nur für Strings um Indexen zu erzeugen, danach geht es zu einer C-Funktion.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 22.10.2010, 15:26     Titel:
  Antworten mit Zitat      
Hallo Denny,

denny hat Folgendes geschrieben:
@Sco du hast 2 Schleifen. BSXFUN gehört zu der versteckten Schleifen


Jan S hat Folgendes geschrieben:
UNIQUE und ISMEMBER beinhalten neben den versteckten Schleifen auch noch zwei Sortierungen


denny hat Folgendes geschrieben:
Und? Ich habe diese aber nicht verschachtelt. ISMEMBER ist auf Zahlen sehr schnell, Schleifen braucht es nur für Strings um Indexen zu erzeugen, danach geht es zu einer C-Funktion.


Wenn Du sagst, dass BSXFUN eine versteckte Schleife ist, obwohl es in eine Builtin-Funktion ist, erwähne ich, dass dies für UNIQUE und ISMEMBER auch zutrifft.

Ich habe nicht den Eindruck, dass ISMEMBER schnell ist. Die zugrunde liegende MEX-Funktion ISMEMBC ist recht fix, aber das Sortieren kann das sehr leicht zunichte machen.
Ohne Frage würde ich die von Dir angegebene Lösung empfehlen, wenn das Problem nicht arg zu zeitkritisch ist. Falls aber doch, ist der Overhead deutlich:
1. Sortieren der Daten in UNIQUE(rows)
==> ISMEMBER(rows):
2. Aufruf von UNIQUE für beide Inputs, also nochml 2 Sortierungen
3. SORTROWS([au;su]): Noch eine Sortierung, und dabei wird noch nicht einmal ein MergeSort verwendet, das ausnutzen würde, dass beide Inputs schon sortiert sind.
4. Da ISMEMBER mit mehr als einem Output aufgerufen wird, wird intern nochmals ISMEMBER aufgerufen für "Find repeats among original list". Das sortiert die Indices noch einmal, falls es weniger als 1000 sind. Andernfalls hilft ein zeitraubender ISSORTED-Test das Sortieren zu vermeiden - das ist aber nicht unbedingt schneller.

Eine naive Implementierung als C-Mex, die ganz banal jedes Element aus einem Array mit allen Elementen aus einem zweiten Array vergleicht ist etwa 2 bis 4 mal schneller für kleine Vektoren (etwa NUMEL=100), und bei größeren Vektoren (~1000 Elemente) kommt es auf den Grad der Sortierung an, ob das naive C-Mex oder ISMEMBER schneller ist. Für > 10^5 Elemente ist das Suchen auf jeden Fall aufwändiger als das Sortieren. Ein einmaliges Sortieren wäre aber auf alle Fälle sinnig.

Für Cell Strings habe ich die entsprechende Methode veröffentlicht:
http://www.mathworks.com/matlabcentral/fileexchange/24380

Das betrifft aber nun nicht ISMEMBER(rows)!
Ich werde das mal als C-Mex versuchen, wenn ich Zeit dafür finde.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 24.10.2010, 13:33     Titel:
  Antworten mit Zitat      
Zitat:
Wenn Du sagst, dass BSXFUN eine versteckte Schleife ist, obwohl es in eine Builtin-Funktion ist, erwähne ich, dass dies für UNIQUE und ISMEMBER auch zutrifft.


Das ist mir klar, überall wo Sortieren/ Suchen vorkommt, sind Schleifen nötig. Ich wollte bloß damit sagen, dass Sco hat BSXFUN in eigenen verschachtelt, also hat er in schlimmsten Fall schon Laufzeit von O(n³), ich habe zwar auch Schleifen, habe aber in schlimmsten Fall Laufzeit etwa von O(2n²+n)=O(n²)
Ich will damit sagen, dass Vorschachtelung ist der Oberkiller, mag sein die Befehle führen doppelte Operationen aus und die Laufzeit verdoppelt sich dadurch. Aber dass ist halt wie ich es mit Matlab internen Funktionen zu Lösung komme.

Ich glaube schon, dass du bei Cell viel rausholen kannst, bei Zahlen-Matrizen bin ich da skeptischer. Matlab ist ja auf Matrizen optimiert. Da bin ich auf deine Mex-Lösung gespannt.

Mich hätte aber noch mehr interessiert, wie du es mit Matlab mitteln gelöst hättest, das wäre für viele hier die mit C/C++ nicht arbeiten bestimmt interessanter.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 24.10.2010, 16:42     Titel:
  Antworten mit Zitat      
Hallo Denny,

Zitat:
Ich glaube schon, dass du bei Cell viel rausholen kannst, bei Zahlen-Matrizen bin ich da skeptischer.

Ich auch.

Zitat:
Mich hätte aber noch mehr interessiert, wie du es mit Matlab mitteln gelöst hättest, das wäre für viele hier die mit C/C++ nicht arbeiten bestimmt interessanter.

Das ist ja immerhin auch ein Matlab-Forum. Also:
Code:
% VERSION 1
x = fix(rand(16, 2) * 4);  % Small test data to check results
[a, b, c] = unique(x, 'rows');
[u, v] = histc(c, 1:max(c));
Z = [x, u(v)];
 

Ein ISMEMBER(rows) kann man sparen, wenn man UNIQUE(rows) mit drei Outputs benutzt. HISTC ist als built-in (C-Mex) Funktion schneller als eine Schleife und "sum(pos==k)" (aus Dennies Lösung).

Nun ist HISTC noch ziemlich flexibel und würde auch Werte zwischen den ganzzahligen Schritten akzeptieren. ACCUMARRAY ist etwas einfacher gestrickt und damit auch schneller:
Code:
% VERSION 2
[a, b, c] = unique(x, 'rows');
f = accumarray(c, 1);
Z = [x, f(c)];
 

14% schneller als mit HISTC (2009a, 1600 x 2 matrix).

Eine weitere Verbesserung ist es, SORTROWS aus UNQIUE explizit auszuführen und danach auszunutzen, dass die Werte bereits sortiert sind:
Code:
% VERSION 3
m = size(x, 1);
[v, ind1] = sort(x(:,    2));   % Inlined SORTROWS
[v, ind2] = sort(x(ind1, 1));
ind = ind1(ind2);

y = x(ind, :);
d(2:m) = any(diff(y, 1, 1), 2);  % Find indices where values change
d(1)   = true;

Dist = diff([find(d), m+1]);  % Calculate distance between changes
list(ind) = Dist(cumsum(d));
Z = [x, list(:)];
 

40% schneller als mit HISTC. Aber ziemlich unübersichtlich. Ehrlich gesagt ist es optisch gesehen sogar richtig häßlich. Wenn also irgend jemand verstehen möchte, was genau geschieht, wird das sicherlich mehr Zeit kosten, als die tolle Laufzeit jemals wieder einbringen wird. Deshalb empfehele ich:
- Version1 für alte Matlab Versionen (kein ACCUMARRAY),
- Version2 für interessierte Nutzer eines neuen Matlab,
- Version3 falls die Laufzeit wirklich wichtig wird und niemand das Programm später debuggen muss.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 25.10.2010, 11:56     Titel:
  Antworten mit Zitat      
@Jan

Gleich mehrere Lösungsvorschläge, sehr schön, gut erklärt Jan. Konnte einiges lernen von dir. Danke
Private Nachricht senden Benutzer-Profile anzeigen
 
Paul222

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 25.10.2010, 17:44     Titel:
  Antworten mit Zitat      
Da kann ich nur zustimmen... Ich ziehe meinen Hut!

Herzlichen Dank
LG Paul
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 25.10.2010, 17:51     Titel:
  Antworten mit Zitat      
Hallo Paul, hallo Denny,

Gerne. Ich habe alle drei Möglichkeiten ausprobiert, um zu testen, was eigentlich schneller ist - das kann aber je nach Matlab-Version anders ausfallen: Manchmal kann der JIT-Compiler einer neuen Version genau erkennen, was der Programmierer eigentlich wollte, und das drastisch beschleunigen.
Und als ich nun schon drei Versionen eingetippt hatte, konnte ich sie auch gleich posten.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.