r - 在 group_by() %>% mutate() 函数调用中使用带引号的变量
问题描述
可重现的例子
cats <-
data.frame(
name = c(letters[1:10]),
weight = c(rnorm(5, 10, 1), rnorm(5, 20, 3)),
type = c(rep("not_fat", 5), rep("fat", 5))
)
get_means <- function(df, metric, group) {
df %>%
group_by(.[[group]]) %>%
mutate(mean_stat = mean(.[[metric]])) %>%
pull(mean_stat) %>%
unique()
}
get_means(cats, metric = "weight", group = "type")
我试过的
我希望得到两个值,而不是得到一个值。看来 groupby 失败了。
我尝试了所有方法,包括使用 quo()、eval() 和替代()、UQ()、!! 以及其他一大堆东西来尝试使 group_by() 中的东西正常工作。
这似乎非常简单,但我无法弄清楚。
代码推理
将变量放在引号中的决定是因为我在 ggplot aes_string() 调用中使用它们。我在函数中排除了 ggplot 代码以简化代码,否则会很容易,因为我们可以使用标准评估。
解决方案
我认为在 tidyeval 框架中执行此操作的“预期”方法是将参数作为名称(而不是字符串)输入,然后使用enquo()
. ggplot2
了解整洁的评估运算符,因此这也适用ggplot2
。
首先,让我们dplyr
在您的示例中调整汇总函数:
library(tidyverse)
library(rlang)
get_means <- function(df, metric, group) {
metric = enquo(metric)
group = enquo(group)
df %>%
group_by(!!group) %>%
summarise(!!paste0("mean_", as_label(metric)) := mean(!!metric))
}
get_means(cats, weight, type)
type mean_weight 1 fat 20.0 2 not_fat 10.2
get_means(iris, Petal.Width, Species)
Species mean_Petal.Width 1 setosa 0.246 2 versicolor 1.33 3 virginica 2.03
现在添加ggplot:
get_means <- function(df, metric, group) {
metric = enquo(metric)
group = enquo(group)
df %>%
group_by(!!group) %>%
summarise(mean_stat = mean(!!metric)) %>%
ggplot(aes(!!group, mean_stat)) +
geom_point()
}
get_means(cats, weight, type)
我不确定您想到的是哪种类型的图,但您可以使用 tidy 评估来绘制数据和汇总值。例如:
plot_func = function(data, metric, group) {
metric = enquo(metric)
group = enquo(group)
data %>%
ggplot(aes(!!group, !!metric)) +
geom_point() +
geom_point(data=. %>%
group_by(!!group) %>%
summarise(!!metric := mean(!!metric)),
shape="_", colour="red", size=8) +
expand_limits(y=0) +
scale_y_continuous(expand=expand_scale(mult=c(0,0.02)))
}
plot_func(cats, weight, type)
仅供参考,您可以允许函数使用...
参数而enquos
不是使用任意数量的分组变量(包括无) enquo
(这也需要使用!!!
(unquote-splice) 而不是!!
(unquote))。
get_means <- function(df, metric, ...) { metric = enquo(metric) groups = enquos(...) df %>% group_by(!!!groups) %>% summarise(!!paste0("mean_", quo_text(metric)) := mean(!!metric)) }
get_means(mtcars, mpg, cyl, vs)
cyl vs mean_mpg 1 4 0 26 2 4 1 26.7 3 6 0 20.6 4 6 1 19.1 5 8 0 15.1
get_means(mtcars, mpg)
mean_mpg 1 20.1
推荐阅读
- c# - 使用 datetime.parseexact() 函数在 C# windows 应用程序窗体中更改系统日期和时间格式
- string - 如何从字符串文字中每行写入一定数量的字符?
- web-scraping - 将输出 (println!) 转换为 .csv 文件
- http - 如何将具有多值的字段设置为 Post 请求?
- php - Laravel 8 验证仅接受以下内容
- azure - 在 Azure 室内地图中基于缩放级别渲染对象
- tensorflow - BERT 分类器# ValueError:没有为任何变量提供梯度:
- arrays - 在 PostgreSQL 中提取和展平 JSON
- javascript - 触发一次后删除滚动事件监听器
- java - 文件。带有 FileNameFilter 的 ListFiles 返回 null 而不是具有匹配文件名的文件列表