2014-10-31 5 views
5

Ich habe eine Matrix (A) in Form von (viel größer in der Realität):Auszählung Co-Inzidenz von Zahlen in den Spalten einer Matrix - MATLAB

205 204 201 
202 208 202 

Wie kann ich die Koinzidenz von Tally Zahlen auf einer spaltenweisen Basis und geben Sie diese dann an eine Matrix aus?

Ich möchte die endgültige Matrix von min (A): max (A) laufen lassen (oder in der Lage sein, einen bestimmten Bereich zu spezifizieren) über die Oberseite und die Seite und damit Co-Inzidenzen von Zahlen zu zählen in jeder Spalte. Im obigen Beispiel:

200 201 202 203 204 205 206 207 208 
200 0 0 0 0 0 0 0 0 0 
201 0 0 1 0 0 0 0 0 0 
202 0 0 0 0 0 1 0 0 0 
203 0 0 0 0 0 0 0 0 0 
204 0 0 0 0 0 0 0 0 1 
205 0 0 0 0 0 0 0 0 0 
206 0 0 0 0 0 0 0 0 0 
207 0 0 0 0 0 0 0 0 0 
208 0 0 0 0 0 0 0 0 0 

(Matrix-Etiketten sind nicht erforderlich)

Zwei wichtige Punkte: Die Auszählung nicht-Vervielfältigen sein muss und in numerischer Reihenfolge auftreten. Zum Beispiel einer Spalte mit:

205 
202 

Wird Tally dies als 202 mit 205 auftritt, aber nicht 205 mit 202 (wie in der obigen Matrix dargestellt) - das Duplikat auf Gegenseitigkeit. Wenn Sie entscheiden, welche Nummer als Referenz verwendet werden soll, sollte sie die kleinste sein.

EDIT:

enter image description here

Antwort

4

sparse zur Rettung!

Ihre Daten und gewünschten Bereich Lassen als

A = [ 205 204 201 
     202 208 202 ]; %// data. Two-row matrix 
limits = [200 208]; %// desired range. It needn't include all values of A 

Dann

lim1 = limits(1)-1; 
s = limits(2)-lim1; 
cols = all((A>=limits(1)) & (A<=limits(2)), 1); 
B = sort(A(:,cols), 1, 'descend')-lim1; 
R = full(sparse(B(2,:), B(1,:), 1, s, s)); 

gibt

R = 
    0  0  0  0  0  0  0  0  0 
    0  0  1  0  0  0  0  0  0 
    0  0  0  0  0  1  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 

Alternativ definiert werden, können Sie mit sort und Verwendung Matrix zusätzlich durch triu gefolgt verzichtet werden kann um das gleiche Ergebnis zu erhalten (möglicherweise fas ter):

lim1 = limits(1)-1; 
s = limits(2)-lim1; 
cols = all((A>=limits(1)) & (A<=limits(2)) , 1); 
R = full(sparse(A(2,cols)-lim1, A(1,cols)-lim1, 1, s, s)); 
R = triu(R + R.'); 

Beide Ansätze behandeln wiederholte Spalten (bis zur Sortierung) und erhöhen korrekt ihre Tally. Zum Beispiel

A = [205 204 201 
    201 208 205] 

gibt

R = 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  2  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
3

sehen, ob dies ist, was Sie waren nach -

range1 = 200:208 %// Set the range 

A = A(:,all(A>=min(range1)) & all(A<=max(range1))) %// select A with columns 
                %// that fall within range1 
A_off = A-range1(1)+1 %// Get the offsetted indices from A 

A_off_sort = sort(A_off,1) %// sort offset indices to satisfy "smallest" criteria 

out = zeros(numel(range1)); %// storage for output matrix 
idx = sub2ind(size(out),A_off_sort(1,:),A_off_sort(2,:)) %// get the indices to be set 

unqidx = unique(idx) 
out(unqidx) = histc(idx,unqidx) %// set coincidences 

Mit

A = [205 204 201 
    201 208 205] 

diese bekommt -

out = 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  2  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 

Nur wenige leistungsorientierte Tricks hier werden könnte -

I.

ersetzen
out = zeros(numel(range1)); 

mit

out(numel(range1),numel(range1)) = 0; 

II. Ersetzen

idx = sub2ind(size(out),A_off_sort(1,:),A_off_sort(2,:)) 

mit

idx = (A_off_sort(2,:)-1)*numel(range1)+A_off_sort(1,:) 
+0

Ich denke, die Fragesteller Zahlen größer als 1 im Ergebnis will, wenn die gleiche Spalte (bis zu sortieren) für die Köpfe dort mehr als einmal –

+0

@LuisMendo Dank erscheint, herausgegeben! +1 für dich! – Divakar

+0

Gute Lösung! +1 auch jetzt –

3

Was ist eine Lösung mit accumarray? Ich würde zuerst jede Spalte unabhängig sortieren und dann die erste Zeile als erste Dimension in die endgültige Akkumulationsmatrix und dann die zweite Zeile als zweite Dimension in die endgültige Akkumulationsmatrix verwenden. Etwas wie:

limits = 200:208; 
A = A(:,all(A>=min(limits)) & all(A<=max(limits))); %// Borrowed from Divakar 

%// Sort the columns individually and bring down to 1-indexing 
B = sort(A, 1) - limits(1) + 1; 

%// Create co-occurrence matrix 
C = accumarray(B.', 1, [numel(limits) numel(limits)]); 

mit:

A = [205 204 201 
    202 208 202] 

Dies ist die Ausgabe:

C = 

    0  0  0  0  0  0  0  0  0 
    0  0  1  0  0  0  0  0  0 
    0  0  0  0  0  1  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 

Mit Duplikate (entlehnt Luis Mendo):

A = [205 204 201 
    201 208 205] 

Ausgang:

C = 

    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  2  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  1 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
    0  0  0  0  0  0  0  0  0 
+0

Scheint gut zu funktionieren! Eigentlich ein guter Job, denn der Code ist auch ziemlich kompakt. Sieht aus, als wärst du gut in akkumarray-ding geworden! – Divakar

+0

@Divakar - Haha danke :) Ich lernte von chappjc. Es ist sehr einfach zu bedienen, sobald Sie den Dreh raus haben. – rayryeng

+0

Das sieht nach einer wirklich schönen kompakten Lösung aus. Ich habe jedoch immer noch Probleme bei der Verarbeitung meiner ursprünglichen Matrix mit A = A (:, alle (A> = min (Grenzen)) und alle (A <= max (Grenzen))); dies ergibt einfach eine leere Matrix = [] trotz Werten zwischen den vorhandenen Grenzen. Es funktioniert nur, wenn die Grenzwerte 0 als Mindestwert enthalten. Die ursprüngliche Matrix enthält Nullen in einigen Zeilen, aber ich kann nicht sehen, warum es nicht auf diese Weise verarbeiten würde. – AnnaSchumann

Verwandte Themen