【问题标题】:How to select the rows with maximum values in each group with dplyr? [duplicate]如何使用 dplyr 选择每组中具有最大值的行? [复制]
【发布时间】:2014-08-05 21:45:43
【问题描述】:

我想用 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        

【问题讨论】:

    标签: r dplyr plyr greatest-n-per-group


    【解决方案1】:

    试试这个:

    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
    

    正如 cmets 中所指出的,如果您严格只希望每组 1 行,则 slice 在此处可能是首选,如 @RoyalITS' answer below。如果有多个具有相同最大值的行,则此答案将返回多行。

    【讨论】:

    • 在这种情况下,结果是相同的,因为不存在重复的最大值。否则,filter 方法将返回每组的所有最大值(行),而 OP 的 ddply 方法与which.max 将只返回每组一个最大值(第一个)。要复制该行为,另一种选择是在 dplyr 中使用 slice(which.max(value))
    • 根据@talat 注释,使用filter(row_number()==1) 可以获得相同的结果。分组前记得安排DF
    【解决方案2】:
    df %>% group_by(A,B) %>% slice(which.max(value))
    

    【讨论】:

    • slice_max(.data, order_by, ..., n, prop, with_ties = TRUE) 现在也是一个不错的选择...
    【解决方案3】:

    你可以使用top_n

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

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

    目前,您无法更改此默认设置而不会导致错误(请参阅https://github.com/hadley/dplyr/issues/426

    【讨论】:

    • 请注意,平局会导致重复。
    • 如果你的值不是最后一列你可以使用top_n的wt参数df %&gt;% group_by(A,B) %&gt;% top_n(n=1, wt = value)
    【解决方案4】:

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

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

    【讨论】:

    • 我觉得这个方法不错,谢谢分享。
    【解决方案5】:

    更一般地说,我认为您可能希望获得给定组中排序的行的“顶部”。

    对于单个值被最大化的情况,您基本上只按一列排序。但是,按多列进行分层排序通常很有用(例如:日期列和时间列)。

    # 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()
    

    【讨论】:

    • 当你arrange( desc(value) )然后值被分组?我想在那里说 C 的总和。
    • @PrzemyslawRemin,我不确定我是否完全理解“C 的总和”在哪里或您打算如何使用它。在dplyr 中,很高兴将您的步骤分开。您可以 df %&gt;% group_by( A, B) %&gt;% mutate( s = sum(C) ) 将每个组中的 C 的总和作为(重复)值 s 放入每个组中(每行在组中获得相同的总和值)。然后你可以ungroup 并使用描述的其他方法之一来过滤 C 的最大值,例如... %&gt;% ungroup() %&gt;% slice(which.max(C))
    【解决方案6】:

    对我来说,计算每组值的数量很有帮助。将计数表复制到一个新对象中。然后根据第一个分组特征过滤组的最大值。例如:

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

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

    【讨论】:

    • 如果您对问题中的数据运行此命令,我想您会发现它回答了错误的问题。帖子中的问题是关于如何找到具有最大值的行(value 列中的数字)。此答案忽略value 列,以查找每个A 最常见的B 值。
    猜你喜欢
    • 1970-01-01
    • 2021-08-04
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 2014-08-24
    • 1970-01-01
    相关资源
    最近更新 更多