2014-06-16 18 views
54

Ich möchte mit dplyr eine Zeile mit maximalem Wert in jeder Gruppe auswählen.Wie wählt man die Zeilen mit maximalen Werten in jeder Gruppe mit dplyr?

Erstens erzeugen ich einige Zufallsdaten meine Frage

set.seed(1) 
df <- expand.grid(list(A = 1:5, B = 1:5, C = 1:5)) 
df$value <- runif(nrow(df)) 

In plyr zu zeigen, ich eine benutzerdefinierte Funktion verwenden, könnte diese Zeile auszuwählen.

library(plyr) 
ddply(df, .(A, B), function(x) x[which.max(x$value),]) 

In dplyr ich diesen Code bin mit dem Maximalwert zu erhalten, aber nicht die Zeilen mit Maximalwert (Spalte C in diesem Fall).

library(dplyr) 
df %>% group_by(A, B) %>% 
    summarise(max = max(value)) 

Wie konnte ich das erreichen? Danke für jeden Vorschlag.

sessionInfo() 
R version 3.1.0 (2014-04-10) 
Platform: x86_64-w64-mingw32/x64 (64-bit) 

locale: 
[1] LC_COLLATE=English_Australia.1252 LC_CTYPE=English_Australia.1252 
[3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C      
[5] LC_TIME=English_Australia.1252  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] dplyr_0.2 plyr_1.8.1 

loaded via a namespace (and not attached): 
[1] assertthat_0.1.0.99 parallel_3.1.0  Rcpp_0.11.1   
[4] tools_3.1.0   

Antwort

64

Try this:

result <- df %>% 
      group_by(A, B) %>% 
      filter(value == max(value)) %>% 
      arrange(A,B,C) 

scheint zu funktionieren:

identical(
    as.data.frame(result), 
    ddply(df, .(A, B), function(x) x[which.max(x$value),]) 
) 
#[1] TRUE 

Wie @docendo in den Kommentaren darauf hingewiesen, slice kann hier bevorzugt werden, da pro @RoyalITS‘Antwort unten wenn Sie nur eine Zeile pro Gruppe haben wollen. Diese Antwort gibt mehrere Zeilen zurück, wenn mehrere mit einem identischen Maximalwert vorliegen.

+11

Die Ergebnisse sind in diesem Fall identisch, da keine doppelten Maximalwerte vorhanden sind. Andernfalls würde der "Filter" -Ansatz alle maximalen Werte (Zeilen) pro Gruppe zurückgeben, während die ddply-Annäherung des OP mit 'which.max' nur ein Maximum (das erste) pro Gruppe zurückgeben würde. Um dieses Verhalten zu replizieren, besteht eine andere Möglichkeit darin, 'slice (which.max (value))' in dplyr zu verwenden. –

40

können Sie top_n

df %>% group_by(A, B) %>% top_n(n=1) 

verwenden Dies wird durch die letzte Spalte einordnet (value) und die oberen n=1 Zeilen zurück.

Derzeit können Sie nicht ohne die diese Standardeinstellung ändern, einen Fehler verursacht (https://github.com/hadley/dplyr/issues/426 Siehe)

29
df %>% group_by(A,B) %>% slice(which.max(value)) 
7

Diese ausführlichere Lösung bietet mehr Kontrolle darüber, was im Falle eines doppelten Maximalwert geschieht (in diesem Beispiel, es wird eine der entsprechenden Zeilen nach dem Zufallsprinzip ausgewählt)

library(dplyr) 
df %>% group_by(A, B) %>% 
    mutate(the_rank = rank(-value, ties.method = "random")) %>% 
    filter(the_rank == 1) %>% select(-the_rank)