2014-06-16 60 views
54

我想用dplyr在每個組中選擇一個最大值的行。如何用dplyr選擇每個組中具有最大值的行?

首先我產生一些隨機數據,以顯示我的問題

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

在plyr,我可以使用自定義功能選擇該行。

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

在dplyr中,我使用此代碼來獲取最大值,但不是具有最大值的行(本例中爲C列)。

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

我怎麼能做到這一點?感謝您的任何建議。

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   

回答

64

試試這個:

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

似乎工作:

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

正如在評論@docendo指出,slice在這裏可以優先按照以下@RoyalITS的回答如果你嚴格只需要每組1行。如果有多個具有相同的最大值,此答案將返回多行。

+11

結果在這種情況下是相同的,因爲沒有重複出現的最大值。否則,'filter'方法將返回每個組的所有最大值(行),而OP的ddply方法和'which.max'只會返回每個組的最大值(第一個)。爲了複製這種行爲,另一種選擇是在dplyr中使用'slice(which.max(value))'。 –

40

您可以使用top_n

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

這將通過最後一列(value)排名,並返回頂部n=1行。

目前,你不能沒有導致錯誤更改此默認(參見https://github.com/hadley/dplyr/issues/426

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

這更詳細的解決方案提供了在重複的最大值的情況下會發生什麼更大的控制(在這個例子中,它將隨機取對應的一行)

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