最终目标是参数化参数(本例中为
yval
),以便可以生成多个报告。
我遇到了 ggplot 函数没有按照我想要的方式解释全局值的问题。我确信这是我对 NSE 的误解,但在这里还没有找到答案。
仅当显式输入
yvar
而不是通过全局变量传递时才有效。
我想用这个创建一个函数,然后将不同的值传递给x、y、颜色等。
library(ggplot2)
ggplot(mtcars, aes(cyl, mpg,
color=factor(vs))) +
geom_point()
pl_test <- function(df, xvar, yvar, gvar){
ggplot(df, aes(!!ensym(xvar), !!ensym(yvar),
color={{gvar}})) +
geom_point() }
mtcars$vs <- factor(mtcars$vs)
# works fine
pl_test(mtcars, cyl, mpg, vs)
# doesn't interpret yvar correctly
yvar_for_plot <- "mpg"
pl_test(mtcars, cyl, yvar_for_plot, vs)
# doesn't work
yvar_for_plot <- sym("mpg")
pl_test(mtcars, cyl, yvar_for_plot, vs)
#> Don't know how to automatically pick scale for object of type <name>.
#> Defaulting to continuous.
#> Error in `geom_point()`:
#> ! Problem while computing aesthetics.
#> ℹ Error occurred in the 1st layer.
#> Caused by error in `compute_aesthetics()`:
#> ! Aesthetics are not valid data columns.
#> ✖ The following aesthetics are invalid:
#> ✖ `y = yvar_for_plot`
#> ℹ Did you mistype the name of a data column or forget to add `after_stat()`?
创建于 2024 年 11 月 16 日,使用 reprex v2.1.1
问题是您希望函数能够以两种截然不同的方式处理参数:它应该能够将不带引号的列名直接作为符号传递,但有时并且没有特定的指令也应该意识到传递的符号不是列名,而是代表调用环境中变量的符号,应对其进行求值并将其从字符串转换为符号。
您需要编写条件代码来识别用户可能的意图并为其生成适当的符号。
library(ggplot2)
pl_test <- function(df, xvar, yvar, gvar) {
xvar <- deparse(substitute(xvar))
yvar <- deparse(substitute(yvar))
gvar <- deparse(substitute(gvar))
if(xvar %in% names(df)) {
xvar <- str2lang(xvar)
} else if(xvar %in% ls(envir = parent.frame())) {
xvar <- str2lang(get(xvar, envir = parent.frame()))
}
if(yvar %in% names(df)) {
yvar <- str2lang(yvar)
} else if(yvar %in% ls(envir = parent.frame())) {
yvar <- str2lang(get(yvar, envir = parent.frame()))
}
if(gvar %in% names(df)) {
gvar <- str2lang(gvar)
} else if(gvar %in% ls(envir = parent.frame())) {
gvar <- str2lang(get(gvar, envir = parent.frame()))
}
ggplot(df, aes(!!xvar, !!yvar, color = !!gvar)) +
geom_point()
}
所以现在我们可以做:
mtcars$vs <- factor(mtcars$vs)
yvar_for_plot <- "mpg"
pl_test(mtcars, cyl, mpg, vs)
还有
pl_test(mtcars, cyl, yvar_for_plot, vs)