在 ggplot2 的函数调用 aes 中混合点和命名参数
Mix dots and named arguments in function calling aes for ggplot2
我正在尝试围绕 ggplot
创建一个包装器,它允许我添加一些美学效果,例如 x 变量或颜色,但总是预填充 y
、ymin
和 ymax
无需使用带引号的变量名。
因为 ggplot2 不能使用 tidy evaluation 我必须为此使用 NSE 但我被卡住了,我能找到的信息 here and here 和检查一些函数让我尝试了 unlist(...)
和工作match.call()
。但他们只会抛出不同的错误。
在下面的函数中,我基本上希望能够调用 ci_plot()
或者例如 ci_plot(color = cyl)
library(dplyr)
library(ggplot2)
library(purrr)
library(tidyr)
ci_plot <- function(data, ...) {
ggplot(data, aes(..., y = y, ymin = ymin, ymax = ymax))
}
mpg %>%
group_by(manufacturer) %>%
nest() %>%
mutate(x = map(data, ~mean_se(.x$hwy))) %>%
unnest(x) %>%
ci_plot() +
geom_pointrange()
您有几个选项,具体取决于您希望用户如何将变量传递给函数。
使用字符串和aes_string
您可以让用户通过字符串提供变量。在这种情况下,您希望 aes_string
中的 ...
然后为 "fixed" 变量添加一个单独的 aes
层。
你的数据操作代码为我返回了所有 NA
,所以这个例子更简单。我将 y
变量固定为 cty
.
ci_plot = function(data, ...) {
ggplot(data, aes_string(...) ) +
aes( y = cty )
}
ci_plot(data = mpg, x = "displ", color = "class") +
geom_point()
使用波浪号和 aes_
另一种方法是让用户在使用该函数时对变量使用波浪号。在这种情况下,aes_
可用于固定变量和可变变量。
ci_plot2 = function(data, ...) {
ggplot(data, aes_(..., y = ~cty ) )
}
ci_plot2(data = mpg, x = ~displ, color = ~class) +
geom_point()
两个函数的结果图:
经过更多的挖掘,我找到了 shadow 的答案 here 并弄清楚了如何根据我的目的调整它。
我会尽量概述解决方案。
ci_plot <- function(data, ...) {
# Create a list of unevaluated parameters,
# removing the first two, which are the function itself and data.
arglist <- as.list(match.call()[-c(1,2)])
# We can add additional parameters to the list using substitute
arglist$ymin = substitute(ymin)
arglist$y = substitute(y)
arglist$ymax = substitute(ymax)
# I suppose this allows ggplot2 to recognize that it needs to quote the arguments
myaes <- structure(arglist, class="uneval")
# And this quotes the arguments?
myaes <- ggplot2:::rename_aes(myaes)
ggplot(data, myaes)
}
那个函数允许我这样写代码
mpg %>%
group_by(manufacturer, cyl) %>%
nest() %>%
mutate(x = map(data, ~mean_se(.x$hwy))) %>%
unnest(x) %>%
ci_plot(x = cyl, color = manufacturer) +
geom_pointrange()
我正在尝试围绕 ggplot
创建一个包装器,它允许我添加一些美学效果,例如 x 变量或颜色,但总是预填充 y
、ymin
和 ymax
无需使用带引号的变量名。
因为 ggplot2 不能使用 tidy evaluation 我必须为此使用 NSE 但我被卡住了,我能找到的信息 here and here 和检查一些函数让我尝试了 unlist(...)
和工作match.call()
。但他们只会抛出不同的错误。
在下面的函数中,我基本上希望能够调用 ci_plot()
或者例如 ci_plot(color = cyl)
library(dplyr)
library(ggplot2)
library(purrr)
library(tidyr)
ci_plot <- function(data, ...) {
ggplot(data, aes(..., y = y, ymin = ymin, ymax = ymax))
}
mpg %>%
group_by(manufacturer) %>%
nest() %>%
mutate(x = map(data, ~mean_se(.x$hwy))) %>%
unnest(x) %>%
ci_plot() +
geom_pointrange()
您有几个选项,具体取决于您希望用户如何将变量传递给函数。
使用字符串和aes_string
您可以让用户通过字符串提供变量。在这种情况下,您希望 aes_string
中的 ...
然后为 "fixed" 变量添加一个单独的 aes
层。
你的数据操作代码为我返回了所有 NA
,所以这个例子更简单。我将 y
变量固定为 cty
.
ci_plot = function(data, ...) {
ggplot(data, aes_string(...) ) +
aes( y = cty )
}
ci_plot(data = mpg, x = "displ", color = "class") +
geom_point()
使用波浪号和 aes_
另一种方法是让用户在使用该函数时对变量使用波浪号。在这种情况下,aes_
可用于固定变量和可变变量。
ci_plot2 = function(data, ...) {
ggplot(data, aes_(..., y = ~cty ) )
}
ci_plot2(data = mpg, x = ~displ, color = ~class) +
geom_point()
两个函数的结果图:
经过更多的挖掘,我找到了 shadow 的答案 here 并弄清楚了如何根据我的目的调整它。 我会尽量概述解决方案。
ci_plot <- function(data, ...) {
# Create a list of unevaluated parameters,
# removing the first two, which are the function itself and data.
arglist <- as.list(match.call()[-c(1,2)])
# We can add additional parameters to the list using substitute
arglist$ymin = substitute(ymin)
arglist$y = substitute(y)
arglist$ymax = substitute(ymax)
# I suppose this allows ggplot2 to recognize that it needs to quote the arguments
myaes <- structure(arglist, class="uneval")
# And this quotes the arguments?
myaes <- ggplot2:::rename_aes(myaes)
ggplot(data, myaes)
}
那个函数允许我这样写代码
mpg %>%
group_by(manufacturer, cyl) %>%
nest() %>%
mutate(x = map(data, ~mean_se(.x$hwy))) %>%
unnest(x) %>%
ci_plot(x = cyl, color = manufacturer) +
geom_pointrange()