在 R dplyr 包中向 summarize_at 添加额外变量

Adding extra variables to summarize_at in the R dplyr package

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

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 ,但我只需要 mean 作为 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))

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

这是一个选项,我们可以使用 mutate(然后也将其添加到 group_by)或直接在 group_by 之后创建一个变量 'y_avg' 'treatment' 分组数据,然后执行 summarise_at

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 只有感兴趣的变量,在按 'treatment' 分组后使用 mutatemutate_at 更新列,然后 [=数据集的 23=] 行

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

我们可以 group_by treatment 使用 mutate 计算 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