Dplyr group_by汇总,以保持组中每一列的最小值/最大值,具体取决于列的后缀

时间:2019-06-13 15:39:43

标签: r dplyr

我有一个数据框,其中包含要折叠成单个条目的组,以使新行的值是每个组中的最小值或最大值,具体取决于列名。

例如,给定:

set.seed(1)
dat <- data.frame(grp = c('A', 'A', 'B', 'B'), 
                  v1_high = rnorm(4), 
                  v2_high = rnorm(4), 
                  v3_low = rnorm(4))
# original
   grp    v1_high    v2_high     v3_low
 1   A -0.6264538  0.3295078  0.5757814
 2   A  0.1836433 -0.8204684 -0.3053884
 3   B -0.8356286  0.4874291  1.5117812
 4   B  1.5952808  0.7383247  0.3898432

我想生成一个新的数据帧,其中包含与组“ A”和“ B”相对应的两个条目,每列的最大值以_high结尾,每列的最小值以{{ 1}}。

在这种情况下:

_low

最后,这些列的数目和名称事先未知。

理想情况下,汇总也可以处理没有# desired result grp v1_high v2_high v3_low 1 A 0.1836433 0.3295078 -0.3053884 2 B 1.5952808 0.7383247 0.3898432 列且只有_min列的情况,尽管我总是可以手动检查此情况并分别使用两种方式处理这两种情况_max语句。

有什么建议吗?使用summarize_at()函数似乎应该可以实现,但是我还没有弄清楚如何将不同的函数应用于不同的列集。

1 个答案:

答案 0 :(得分:1)

一种选择是按“ grp”分组,获得以“ high”(列名)结尾的max列,也将其用作分组列并获得min列以“低”结束

library(dplyr)    
dat %>%
   group_by(grp) %>%  
   mutate_at(vars(ends_with('high')), max) %>% 
   group_by_at(vars(ends_with('high')), .add = TRUE) %>% 
   summarise_at(vars(ends_with('low')), min)
# A tibble: 2 x 4
# Groups:   grp, v1_high [2]
#  grp   v1_high v2_high v3_low
#  <fct>   <dbl>   <dbl>  <dbl>
#1 A       0.184   0.330 -0.305
#2 B       1.60    0.738  0.390

如果没有min

dat[-4] %>%
    group_by(grp) %>%  
    mutate_at(vars(ends_with('high')), max) %>% 
    group_by_at(vars(ends_with('high')), .add = TRUE) %>%   
    summarise_at(vars(ends_with('low')), min)
# A tibble: 2 x 3
# Groups:   grp, v1_high [2]
#  grp   v1_high v2_high
#  <fct>   <dbl>   <dbl>
#1 A       0.184   0.330
#2 B       1.60    0.738

或者另一个选择是map2

library(purrr)
map2(list(min, max), list('low', 'high'), ~ 
      dat %>% 
         select(grp, ends_with(.y)) %>%
         group_by(grp) %>%
         summarise_all(.x)) %>% 
         reduce(inner_join, by = 'grp')