取 dplyr 中字符串定义的变量的平均值

take mean of variable defined by string in dplyr


看起来这应该很容易,但我很难过。我已经掌握了使用 dplyr 0.7 进行编程的粗略技巧,但为此苦苦挣扎:How do I program in dplyr if the variable I want to program will be a string?

我正在抓取一个数据库,出于各种原因想总结一个我知道位置但不知道名称的变量(我想要的总是提供的第一列table,但存储在该列中的变量的名称将根据被抓取的数据库而有所不同)。以 iris 为例,假设我知道我想要的变量在第一列

library(tidyverse)
desired_var <- colnames(iris)[1]
print(desired_var)
"Sepal.Length"

我现在想按Species分组,取desired_var的平均值,即我要执行的是

iris %>% 
group_by(Species) %>% 
summarise(desired_mean = mean(Sepal.Length))

但是,现在我想取由存储在 desired_var

中的字符串定义的列的平均值

我知道如何使用 "bare" Sepal.Length

desired_var <- quo(Sepal.Length)

iris %>% 
group_by(Species) %>% 
summarise(desired_mean = mean(!!desired_var))

但是我到底该如何处理 "Sepal.Length" 而不是 Sepal.Length 的事实,即 desired_var <- "Sepal.Length"

您想了解 tidyeval,这是 tidyverse(参见 here)的一项相当新的功能,更多用于使用 tidyverse 函数创建函数。目前它仅适用于 dplyr,但计划将其扩展到其他 tidyverse 包。

不过,根据您的需要,您真的不需要深入了解,summarize_at 就可以了。此函数允许您扩展您在所选的任何变量中指定的特定操作:

iris %>% 
  group_by(Species) %>% 
  summarise_at(vars(one_of("Sepal.Length", "Sepal.Width")), funs(desired_mean = mean))

# A tibble: 3 x 3
     Species Sepal.Length_desired_mean Sepal.Width_desired_mean
      <fctr>                     <dbl>                    <dbl>
1     setosa                     5.006                    3.428
2 versicolor                     5.936                    2.770
3  virginica                     6.588                    2.974

您可以将变量列表存储到向量中,然后改用该向量:

selected_vectors <- c("Sepal.Length", "Sepal.Width")
iris %>% 
  group_by(Species) %>% 
  summarise_at(vars(one_of(selected_vectors)), funs(desired_mean = mean))

1) 带有 !!sym 的动态变量 使用 sym(或 parse_expr),如下所示:

library(dplyr)
library(rlang)

desired_var <- "Sepal.Length"

iris %>% 
  group_by(Species) %>% 
  summarise(desired_mean = mean(!!sym(desired_var))) %>%
  ungroup

给予:

# A tibble: 3 x 2
     Species desired_mean
      <fctr>        <dbl>
1     setosa        5.006
2 versicolor        5.936
3  virginica        6.588

2) summarise_at 正如@Phil 在 summarise 的特殊情况下的评论中指出的那样,可以在不使用任何 rlang 的情况下这样做设施:

library(dplyr)

desired_var <- "Sepal.Length"

iris %>% 
   group_by(Species) %>% 
   summarise_at(desired_var, funs(mean)) %>%
   ungroup

给予:

# A tibble: 3 x 2
     Species Sepal.Length
      <fctr>        <dbl>
1     setosa        5.006
2 versicolor        5.936
3  virginica        6.588

3) 带!! 的动态变量和名称 如果您需要在 (1) 中动态设置名称,那么试试这个:

library(dplyr)
library(rlang)

desired_var <- "Sepal.Length"

desired_var_name <- paste("mean", desired_var, sep = "_")

iris %>% 
  group_by(Species) %>% 
  summarise(!!desired_var_name := mean(!!sym(desired_var))) %>%
  ungroup

给予:

# A tibble: 3 x 2
     Species mean_Sepal.Length
      <fctr>             <dbl>
1     setosa             5.006
2 versicolor             5.936
3  virginica             6.588