2010-05-12 5 views
9
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 

r<-sapply(split(a.3,a.2),function(x) which.max(x$b.2)) 

a.3[r,] 

gibt den Listenindex, der Index für die gesamte data.framewählen Zeilen mit dem größten Wert der Variablen innerhalb einer Gruppe in r

Im Versuch, den größten Wert von b.2 für jede Untergruppe von a.2 zurückzukehren . Wie kann ich das effizient machen?

+0

Schmelze (a.3, id = c ("a.2")) -> h.2; Umwandlung (h.2, a.2 ~, max) Führt den Trick in diesem Beispiel aus, aber der Computer hat nicht genügend Arbeitsspeicher, wenn ich ihn auf meinen ursprünglichen Datensatz anwende. So hat mir wirklich nicht viel geholfen. – Misha

Antwort

6
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 

Die Antwort von Jonathan Chang bekommt man, was man explizit gefragt, aber ich vermute, dass Sie die aktuelle Zeile aus dem Datenrahmen möchten.

sel <- ave(b.2, a.2, FUN = max) == b.2 
a.3[sel,] 
+0

Das war viel einfacher muss ich zugeben .. Allerdings ist die Logik hinter dem == b.2 über mich hinaus ... – Misha

+0

Die Ave erzeugt einen Vektor, der nur das Maximum von B.2 für jede a.2 enthält. Daher gilt: where it == b.2, das einen Wahrheitswert festlegt, solange der Datenrahmen Zeilen enthält. Sie verwenden den logischen Vektor, um Zeilen im Datenrahmen auszuwählen. Wenn Sie sehen möchten, wie es funktioniert, fügen Sie das Ergebnis des Befehls ave zu Ihrem Datenrahmen hinzu und betrachten Sie es, indem Sie es mit der Spalte b.2 vergleichen - a.3 $ b.max <- ave (B.2, a. 2, FUN = max) . Außerdem könnten Sie die Sel-Variable auch in Zusammenhang mit - a.3 $ sel <- a.3 $ b.2 == a.3 $ b.max setzen. – John

+0

Thx ... Ich weiß Ihre Bemühungen zu schätzen. – Misha

1
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 
m<-split(a.3,a.2) 
u<-function(x){ 
    a<-rownames(x) 
    b<-which.max(x[,2]) 
    as.numeric(a[b]) 
    } 
r<-sapply(m,FUN=function(x) u(x)) 

a.3[r,] 

Das macht den Trick, wenn auch etwas umständlich ... Aber es erlaubt mir, die Reihen für die groupsway größten Werte zu greifen. Irgendwelche anderen Ideen?

1
> a.2<-sample(1:10,100,replace=T) 
> b.2<-sample(1:100,100,replace=T) 
> tapply(b.2, a.2, max) 
1 2 3 4 5 6 7 8 9 10 
99 92 96 97 98 99 94 98 98 96 
8
library(plyr) 
ddply(a.3, "a.2", subset, b.2 == max(b.2)) 
+0

Ich versuchte mit der ddply-Funktion, aber es ist schmerzhaft langsam. Ich habe es nicht getan, aber es dauerte einen Kaffee und einen Ausflug ins Badezimmer, während die Ave-Version nur .2s in meinem ursprünglichen Datensatz (210col * 16000rows) verwendet. – Misha

+1

Das wird in der nächsten Version behoben werden.Aber Sie können nicht erwarten, Antworten zu erhalten, die mit Ihren Daten arbeiten, wenn Sie nicht ein realistisches Beispiel liefern! – hadley

10

Die ddply und ave Ansätze sind beide ziemlich ressourcenintensiv, denke ich. ave schlägt fehl, weil nicht genügend Speicher für mein aktuelles Problem zur Verfügung steht (67.608 Zeilen, wobei vier Spalten die eindeutigen Schlüssel definieren). tapply ist eine praktische Wahl, aber was ich in der Regel tun muss, ist die Auswahl aller ganzen Zeilen mit dem etwas est-Wert für jeden eindeutigen Schlüssel (normalerweise definiert durch mehr als eine Spalte). Die beste Lösung, die ich gefunden habe, ist eine Sortierung durchzuführen und dann die Negation duplicated zu verwenden, um nur die erste Zeile für jeden eindeutigen Schlüssel auszuwählen. Für das einfache Beispiel hier:

a <- sample(1:10,100,replace=T) 
b <- sample(1:100,100,replace=T) 
f <- data.frame(a, b) 

sorted <- f[order(f$a, -f$b),] 
highs <- sorted[!duplicated(sorted$a),] 

denke ich, die Performance-Gewinne über ave oder ddply zumindest erheblich sind. Es ist ein wenig komplizierter für mehrspaltige Schlüssel, aber order behandelt eine ganze Reihe von Dingen zu sortieren und duplicated arbeitet auf Datenrahmen, so ist es möglich, diesen Ansatz weiter zu verwenden.

+0

Dies war am einfachsten zu bedienen und funktioniert gut auf mehreren Spalten - alles, was Sie tun müssen, ist 'Cbind' in' duplicated' zu verwenden. –

0
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 

Mit aggregate, können Sie das Maximum für jede Gruppe in einer Zeile erhalten:

aggregate(a.3, by = list(a.3$a.2), FUN = max) 

Dies erzeugt die folgende Ausgabe:

Group.1 a.2 b.2 
1  1 1 96 
2  2 2 82 
... 
8  8 8 85 
9  9 9 93 
10  10 10 97 
Verwandte Themen