【问题标题】:Adding extra variables to summarize_at in the R dplyr package在 R dplyr 包中添加额外的变量到 summarise_at
【发布时间】:2019-12-20 14:20:12
【问题描述】:

我正在使用 R 的 dplyr 包来获取几个变量的汇总统计信息,其中许多变量的名称都相似。例如,我有数百个变量都命名为doctor_id_X,其中X 是某个整数(例如doctor_id_1doctor_id_33doctor_id_543 等)。我可以很容易地获得这些“doctor_id”变量的最大值,这些变量按treatment1分组,在summarize_at语句中使用所谓的“助手”,如下所示:

mydf %>% group_by(treatment1) %>% 
summarize_at(vars(contains("doctor_id")), max)

但是,除了获得这些max 统计数据之外,我还试图获得一些其他变量的平均值,这些变量的名称与doctor_id 变量之一类似,称为procedure_time。有没有办法通过修改我上面的代码来有效地做到这一点?

为了更好地解释我想要做什么,这是一个数据框的玩具示例:

library(dplyr)
set.seed(20190813)
mydf <- data.frame(treatment1 = sample(LETTERS[1:3], 100, replace=TRUE),
                   treatment2 = sample(LETTERS[4:5], 100, replace=TRUE), 
                   doctor_id_1=rbinom(100, 1, .01),
                   doctor_id_2=rbinom(100, 1, .5),
                   doctor_id_3=rbinom(100, 1, .6),
                   doctor_id_4=rbinom(100, 1, .7),
                   y=rnorm(100))
    head(mydf)

  treatment1 treatment2 doctor_id_1 doctor_id_2 doctor_id_3 doctor_id_4          y
1          A          D           0           0           1           0 -1.1175362
2          A          E           0           0           1           1 -2.2813598
3          A          D           0           1           1           0  0.5886914
4          A          D           0           0           1           1  0.9854405
5          B          E           0           0           1           1  1.8831306
6          A          E           0           1           1           1 -0.3875261

通过doctor_id 变量获取max 值摘要没有问题:

mydf %>% group_by(treatment1) %>% 
   summarize_at(vars(contains("doctor_id")), max)

# A tibble: 3 x 5
  treatment1 doctor_id_1 doctor_id_2 doctor_id_3 doctor_id_4
  <fct>            <int>       <int>       <int>       <int>
1 A                    1           1           1           1
2 B                    0           1           1           1
3 C                    0           1           1           1

但是现在,我还想在汇总语句中找到ymean。我试过了,但没有用:

mydf %>% group_by(treatment1) %>% 
   summarize_at(y_avg=mean(y), vars(y, contains("doctor_id")), max)

但是,我确实注意到,以下内容让我更接近我想要的,只是它为所有 doctor_id 变量和 y 变量生成了 max,但我只需要 @987654344 @ 代表y 变量。

mydf %>% group_by(treatment1) %>% 
summarize_at(vars(y, contains("doctor_id")), max)

# A tibble: 3 x 6
  treatment1     y doctor_id_1 doctor_id_2 doctor_id_3 doctor_id_4
  <fct>      <dbl>       <int>       <int>       <int>       <int>
1 A           1.70           1           1           1           1
2 B           1.88           0           1           1           1
3 C           1.45           0           1           1           1

这也让我很接近,但它为两个变量生成了两个统计数据:

mydf %>% group_by(treatment1) %>% 
   summarize_at(vars(y, contains("doctor_id")), c(max, mean))

所以,总而言之,我的问题是,有没有办法在 summarise_by 语句中使用辅助函数,并且还包括另一个变量的不同统计信息,而不必求助于连接?

【问题讨论】:

    标签: r group-by dplyr summarize


    【解决方案1】:

    这是一种选择,我们可以使用mutate(然后在group_by 中添加)或直接在group_by 中的“治疗”分组数据之后创建变量“y_avg”,然后执行@ 987654324@

    library(dplyr)
    mydf %>%
       group_by(treatment1)  %>%
       group_by(y_avg = mean(y), add = TRUE ) %>% 
       summarize_at(vars(contains("doctor_id")), max)
    # A tibble: 3 x 6
    # Groups:   treatment1 [3]
    #  treatment1    y_avg doctor_id_1 doctor_id_2 doctor_id_3 doctor_id_4
    #  <fct>         <dbl>       <int>       <int>       <int>       <int>
    #1 A          -0.216             0           1           1           1
    #2 B           0.0659            0           1           1           1
    #3 C          -0.00830           1           1           1           1
    

    或者另一种选择是在mutate 中创建“y_avg”,然后在group_by 中使用它

    mydf %>%
       group_by(treatment1) %>%
       mutate(y_avg = mean(y) %>%
       group_by(y_avg, add = TRUE) %>%
       summarize_at(vars(contains("doctor_id")), max)
    

    或者另一种选择是 select 仅关注变量,在按“治疗”分组后使用 mutatemutate_at 更新列,然后是 distinct 数据集的行

    mydf %>%
       select(treatment1, y_avg = y, contains('doctor_id')) %>% 
       group_by(treatment1) %>% 
       mutate(y_avg = mean(y_avg)) %>% 
       mutate_at(vars(contains('doctor_id')), max) %>%
       distinct
    

    或者data.table的选项

    library(data.table)
    setDT(mydf)[, c(.(y_avg = mean(y)), lapply(.SD, max)),
            .(treatment1), .SDcols = grep('doctor_id', names(mydf))]
    #.  treatment1        y_avg doctor_id_1 doctor_id_2 doctor_id_3 doctor_id_4
    #1:          C -0.008299684           1           1           1           1
    #2:          B  0.065875911           0           1           1           1
    #3:          A -0.216200359           0           1           1           1
    

    【讨论】:

    • 这太棒了!非常感谢你。我不确定我是否理解为什么可以这样做,但它确实有效。我将保持开放状态,看看是否还有其他可能的解决方案。如果几个小时后我没有看到更好的解决方案,我会接受。再次感谢!
    • @StatsStudent。使用dplyr,当前未实现对mutate_all/at/if 中不同列的部分不同功能。但是,它可以在data.table 中完成
    【解决方案2】:

    我们可以使用mutategroup_bytreatment 计算ymean,将该列添加到summarise_at 以得到所有列的max

    library(dplyr)
    
    mydf %>% 
      group_by(treatment1) %>% 
      mutate(y_avg = mean(y)) %>%
      summarise_at(vars(y_avg, contains("doctor_id")), max)
    
    # A tibble: 3 x 6
    #  treatment1   y_avg doctor_id_1 doctor_id_2 doctor_id_3 doctor_id_4
    #  <fct>        <dbl>       <int>       <int>       <int>       <int>
    #1 A          -0.192            1           1           1           1
    #2 B          -0.0390           0           1           1           1
    #3 C          -0.165            0           1           1           1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 2017-03-10
      • 2015-03-07
      • 2021-07-18
      • 2018-07-20
      • 2012-02-15
      相关资源
      最近更新 更多