2016-07-29 13 views
1

Ich weiß, dass es ähnliche Fragen gibt, aber ich konnte keine Antwort auf meine Frage finden. Ich versuche, Elemente in einer Matrix zu ranken und dann Daten von 5 höchsten Elementen zu extrahieren.Ranking und Zählen von Matrixelementen in R

Hier ist mein Versuch.

set.seed(20) 
d<-matrix(rnorm(100),nrow=10,ncol=10) 
start<-d[1,1] 
for (i in 1:10) { 
for (j in 1:10) { 
    if (start < d[i,j]) 
    {high<-d[i,j] 
    rowind<-i 
    colind<-j 
    } 
    } 
} 

Obwohl dies mir die Daten des höchsten Elements gibt, einschließlich der Zeilen- und Spaltennummern, kann ich glaube nicht an eine Möglichkeit, das gleiche für Elemente von 2 bis 5. Platz zu tun Ich habe auch versucht

rank(d, ties.method="max") 

Aber es war nicht hilfreich, weil es nur den Rang im Vektorformat ausspuckt. Was ich letztlich will ist ein Datenrahmen (oder jede Art von Tabelle), die Rang, Spaltenname, Zeilenname und die Daten (Anzahl) der höchsten 5 Elemente in der Matrix enthält.

bearbeiten

set.seed(20) 
d<-matrix(rnorm(100),nrow=10,ncol=10) 
d[1,2]<-5 
d[2,1]<-5 
d[1,3]<-4 
d[3,1]<-4 

Danke für die Antworten. Diese funktionierten perfekt für meinen Zweck, aber da ich diesen Code für Korrelationsdiagramm verwende - wo es doppelte Zahlen für jedes Paar gibt - möchte ich nur eine der beiden Zahlen für den Ranking-Zweck zählen. Gibt es eine Möglichkeit, dies zu tun? Vielen Dank.

+0

Ist es nach Zeile oder Spalte? – akrun

+0

Verwenden Sie set.seed, bevor Sie ein zufälliges Beispiel erstellen. Erleichtert die Überprüfung und den Vergleich von Antworten. – Frank

+0

@Frank Danke für den Vorschlag. Habe gerade die Änderung vorgenommen. – sh2657

Antwort

3

Hier ist eine sehr grobe Art und Weise:

DF = data.frame(row = c(row(d)), col = c(col(d)), v = c(d)) 
DF[order(DF$v, decreasing=TRUE), ][1:5, ] 

    row col  v 
91 1 10 2.208443 
82 2 9 1.921899 
3 3 1 1.785465 
32 2 4 1.590146 
33 3 4 1.556143 

Es wäre schön, nur Art teilweise, aber in ?order, sieht es aus wie diese Option für sort, nicht für order nur verfügbar ist.

Wenn die Matrix Zeilen- und Spaltennamen hat, kann es sinnvoll sein, sie anstelle von Zahlen zu sehen. Hier ist, was ich tun könnte:

dimnames(d) <- list(letters[1:10], letters[1:10]) 
DF = data.frame(as.table(d)) 

DF[order(DF$Freq, decreasing=TRUE), ][1:5, ] 

    Var1 Var2  Freq 
91 a j 2.208443 
82 b i 1.921899 
3  c a 1.785465 
32 b d 1.590146 
33 c d 1.556143 

Die Spaltennamen machen nicht viel Sinn hier, leider, aber man kann sie mit names(DF) <- wie gewohnt ändern. Hier

+0

Danke für die Antwort Frank. Gibt es eine Möglichkeit, wie ich anstelle von Zahlen Zeilen- und Spaltennamen aufrufen kann? Wenn ich Spaltennamen (d) <- c ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j") und rownames (d) <- c ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j") – sh2657

+0

@ sh2657 Ich habe eine Problemumgehung hinzugefügt. Dies sollte auch funktionieren, wenn Sie ein Array mit mehr als zwei Dimensionen haben: a = array (1: 8, c (2,2,2)); data.frame (as.table (a)) '. Die Namen entlang jeder Helligkeit werden automatisch ausgefüllt, wenn sie leer sind. – Frank

+0

Funktioniert perfekt für den Zweck. Danke vielmals. – sh2657

2

ist eine Option, mit Matrix

library(Matrix) 
m1 <- summary(Matrix(d, sparse=TRUE)) 
head(m1[order(-m1[,3]),],5) 
# i j  x 
#93 3 10 2.359634 
#31 1 4 2.234804 
#23 3 3 1.980956 
#55 5 6 1.801341 
#16 6 2 1.678989 

Oder verwenden melt

library(reshape2) 
m2 <- melt(d) 
head(m2[order(-m2[,3]), ], 5) 
+0

Kein Grund, die Beispielmatrix des OP als spärlich zu speichern, denke ich. – Frank

+0

@Frank Es ist die "Zusammenfassung" zu bekommen – akrun

+0

Ok, ich sehe. Habe diese Funktion vorher noch nicht benutzt und dachte mir, dass es etwas mit dem Speichern als Sparse zu tun hat, rate nicht. – Frank

1

Hier ist etwas ganz einfach in der Basis R.

# set.seed(20) 
# d <- matrix(rnorm(100), nrow = 10, ncol = 10) 

d.rank <- matrix(rank(-d), nrow = 10, ncol = 10) 

which(d.rank <= 5, arr.ind=TRUE) 
    row col 
[1,] 3 1 
[2,] 2 4 
[3,] 3 4 
[4,] 2 9 
[5,] 1 10 

d[d.rank <= 5] 
[1] 1.785465 1.590146 1.556143 1.921899 2.208443 

Ergebnisse können (einfach) deutlicher gemacht werden (siehe Kommentar von Frank):

cbind(which(d.rank <= 5, arr.ind=TRUE), v = d[d.rank <= 5], rank = rank(-d[d.rank <= 5])) 

    row col  v rank 
[1,] 3 1 1.785465 3 
[2,] 2 4 1.590146 4 
[3,] 3 4 1.556143 5 
[4,] 2 9 1.921899 2 
[5,] 1 10 2.208443 1 
+1

Konnte abwechselnd 'cbind (was (d.rank <= 5, arr.ind = TRUE), v = d [d .rank <= 5]), um zu verdeutlichen, dass Ihre Ergebnisse stimmen mit anderen Antworten. (Ich bin mir nicht sicher, ob mein 'cbind' dort tatsächlich richtig ist.) – Frank

Verwandte Themen