如何使用dplyr选择每组中具有最大值的行?

Ban*_*you 98 r plyr greatest-n-per-group dplyr

我想用dplyr在每个组中选择一个具有最大值的行.

首先,我生成一些随机数据来显示我的问题

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

在plyr中,我可以使用自定义函数来选择此行.

library(plyr)
ddply(df, .(A, B), function(x) x[which.max(x$value),])
Run Code Online (Sandbox Code Playgroud)

在dplyr中,我使用此代码来获取最大值,但不是具有最大值的行(在本例中为C列).

library(dplyr)
df %>% group_by(A, B) %>%
    summarise(max = max(value))
Run Code Online (Sandbox Code Playgroud)

我怎么能实现这个目标?谢谢你的任何建议.

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        
Run Code Online (Sandbox Code Playgroud)

the*_*ail 114

试试这个:

result <- df %>% 
             group_by(A, B) %>%
             filter(value == max(value)) %>%
             arrange(A,B,C)
Run Code Online (Sandbox Code Playgroud)

似乎工作:

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

正如@docendo在评论中指出的那样,slice如果您严格只想要每组1行,可能会根据@RoyalITS的答案在这里首选.如果有多个具有相同的最大值,则此答案将返回多行.

  • 在这种情况下结果是相同的,因为不存在重复的最大值.否则,`filter`方法将返回每组的所有最大值(行),而OP的ddply方法使用`which.max`只返回每组的一个最大值(第一个).要复制该行为,另一个选择是在dplyr中使用`slice(which.max(value))`. (13认同)

mne*_*nel 68

您可以使用 top_n

df %>% group_by(A, B) %>% top_n(n=1)
Run Code Online (Sandbox Code Playgroud)

这将按最后一列(value)排名并返回顶n=1行.

目前,您无法在不导致错误的情况下更改此默认值(请参阅https://github.com/hadley/dplyr/issues/426)

  • 请注意,关系会导致重复. (6认同)
  • 如果您的值不是最后一列,您可以使用 top_n `df %&gt;% group_by(A,B) %&gt;% top_n(n=1, wt = value)` 的 wt 参数 (3认同)

Roy*_*lTS 57

df %>% group_by(A,B) %>% slice(which.max(value))
Run Code Online (Sandbox Code Playgroud)

  • `slice_max(.data, order_by, ..., n, prop, with_ties = TRUE)` 现在也是一个不错的选择...... (12认同)

nas*_*ddd 11

这个更详细的解决方案可以更好地控制在重复最大值的情况下发生的情况(在此示例中,它将随机采用相应的行之一)

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