it-swarm.com.de

Wie wählt man die Zeilen mit Maximalwerten in jeder Gruppe mit dplyr aus

Ich möchte in jeder Gruppe mit dplyr eine Zeile mit maximalem Wert auswählen.

Zunächst generiere ich einige zufällige Daten, um meine Frage zu zeigen

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

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

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

In dplyr verwende ich diesen Code, um den Maximalwert zu erhalten, nicht jedoch die Zeilen mit Maximalwert (Spalte C in diesem Fall).

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

Wie kann 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        
82
Bangyou

Versuche dies:

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 von @docendo in den Kommentaren dargelegt, kann slice hier gemäß der Antwort von @RoyalITS bevorzugt werden, wenn Sie nur eine Zeile pro Gruppe wünschen. Diese Antwort gibt mehrere Zeilen zurück, wenn mehrere mit einem identischen Maximalwert vorhanden sind. 

94
thelatemail

Sie können top_n verwenden

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

Dies wird nach der letzten Spalte (value) eingestuft und gibt die obersten n=1-Zeilen zurück.

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

56
mnel
df %>% group_by(A,B) %>% slice(which.max(value))
47
RoyalTS

Diese ausführlichere Lösung bietet eine bessere Kontrolle darüber, was im Falle eines doppelten Maximalwerts geschieht (in diesem Beispiel wird eine der entsprechenden Zeilen zufällig genommen).

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

Für mich half es, die Anzahl der Werte pro Gruppe zu zählen. Kopieren Sie die Count-Tabelle in ein neues Objekt. Dann filtern Sie das Maximum der Gruppe basierend auf dem ersten Gruppierungsmerkmal. Zum Beispiel:

count_table  <- df %>%
                group_by(A, B) %>%
                count() %>%
                arrange(A, desc(n))

count_table %>% 
    group_by(A) %>%
    filter(n == max(n))

oder

count_table %>% 
    group_by(A) %>%
    top_n(1, n)
0
ksvrd

Im Allgemeinen denke ich, dass Sie die Reihen, die sortiert sind, innerhalb einer Gruppe "an der Spitze" finden möchten. 

Für den Fall, dass ein einzelner Wert maximal ausgegeben wird, haben Sie im Wesentlichen nur eine Spalte sortiert. Es ist jedoch oft nützlich, hierarchisch nach mehreren Spalten zu sortieren (z. B. eine Datums- und eine Uhrzeitspalte). 

# Answering the question of getting row with max "value".
df %>% 
  # Within each grouping of A and B values.
  group_by( A, B) %>% 
  # Sort rows in descending order by "value" column.
  arrange( desc(value) ) %>% 
  # Pick the top 1 value
  slice(1) %>% 
  # Remember to ungroup in case you want to do further work without grouping.
  ungroup()

# Answering an extension of the question of 
# getting row with the max value of the lowest "C".
df %>% 
  # Within each grouping of A and B values.
  group_by( A, B) %>% 
  # Sort rows in ascending order by C, and then within that by 
  # descending order by "value" column.
  arrange( C, desc(value) ) %>% 
  # Pick the one top row based on the sort
  slice(1) %>% 
  # Remember to ungroup in case you want to do further work without grouping.
  ungroup()
0
Kalin