Frage
Verwendung dplyr
, wie wähle ich die obere und untere Beobachtungen / Reihen gruppierten Daten in einer Aussage?
Daten & Beispiel
Gegeben ein Datenrahmen
df <- data.frame(id=c(1,1,1,2,2,2,3,3,3),
stopId=c("a","b","c","a","b","c","a","b","c"),
stopSequence=c(1,2,3,3,1,4,3,1,2))
Ich kann die oberen und unteren Beobachtungen von jeder Gruppe erhalten slice
, indem ich zwei separate Aussagen verwende:
firstStop <- df %>%
group_by(id) %>%
arrange(stopSequence) %>%
slice(1) %>%
ungroup
lastStop <- df %>%
group_by(id) %>%
arrange(stopSequence) %>%
slice(n()) %>%
ungroup
Kann ich diese beiden Statmenets zu einem kombinieren, das sowohl obere als auch untere Beobachtungen auswählt ?
Antworten:
Es gibt wahrscheinlich einen schnelleren Weg:
quelle
rownumber() %in% c(1, n())
würde die Notwendigkeit vermeiden, Vektorscan zweimal_
? dhfilter(row_number() %in% c(1, n()))
Der Vollständigkeit halber: Sie können
slice
einen Indexvektor übergeben:was gibt
quelle
filter
- habe dies nicht getestet, aber siehe hiermtcars[1, ] %>% slice(c(1, n()))
In diesem Sinne hängt die Auswahl zwischen ihnen davon ab, was zurückgegeben werden soll. Ich würde erwarten, dass die Timings nahe beieinander liegen, esn
sei denn, sie sind sehr groß (wo Slice bevorzugt wird), aber ich habe sie auch nicht getestet.Nicht
dplyr
, aber es ist viel direkter mitdata.table
:Detailliertere Erklärung:
Achten Sie darauf , die auschecken Erste Schritte die Wiki für das Erhalten
data.table
Grundlagen abgedecktquelle
df[ df[order(stopSequence), .I[c(1,.N)], keyby=id]$V1 ]
.id
Zweimal erscheinen zu sehen , ist komisch für mich.setDT
Anruf Schlüssel festlegen . Also einorder
Anruf hier nicht nötig.df[order(stopSequence), .SD[c(1L,.N)], by = id]
. Siehe hierid
. Ich denke ,df[order(stopSequence), .SD[c(1L, .N)], keyby = id]
soll über dem Ergebnis den Trick (mit dem kleinen Unterschied zu der Lösung tun wirdkey
edEtwas wie:
Mit können
do
Sie so ziemlich eine beliebige Anzahl von Operationen an der Gruppe ausführen, aber die Antwort von @ jeremycg ist viel besser für genau diese Aufgabe geeignet.quelle
slice
, wiedf %>% arrange(stopSequence) %>% group_by(id) %>% slice(c(1,n()))
do
Beispiel hier zu haben, könnte anderen helfen, wennslice
es nicht funktioniert (dh komplexere Operationen in einer Gruppe). Und du solltest deinen Kommentar als Antwort posten (es ist der beste).Ich kenne die angegebene Frage
dplyr
. Da andere bereits Lösungen mit anderen Paketen veröffentlicht haben, habe ich mich entschlossen, auch andere Pakete zu verwenden:Basispaket:
Datentabelle:
sqldf:
In einer Abfrage:
Ausgabe:
quelle
mit
which.min
undwhich.max
:Benchmark
Es ist auch viel schneller als die aktuell akzeptierte Antwort, da wir den Min- und Max-Wert nach Gruppe finden, anstatt die gesamte stopSequence-Spalte zu sortieren.
quelle
Verwenden von
data.table
:quelle
Ein anderer Ansatz mit lapply und einer dplyr-Anweisung. Wir können eine beliebige Anzahl beliebiger Zusammenfassungsfunktionen auf dieselbe Anweisung anwenden:
Sie könnten beispielsweise auch an Zeilen mit dem maximalen Wert stopSequence interessiert sein und Folgendes tun:
quelle
Eine andere Basis-R-Alternative wäre, zuerst
order
nachid
undstopSequence
,split
basierend aufid
und für jedenid
, wählen wir nur den ersten und letzten Index aus und unterteilen den Datenrahmen unter Verwendung dieser Indizes.Oder ähnlich mit
by
quelle