将全局对象值传递给自定义 ggplot 函数参数

问题描述 投票:0回答:1

问题:将全局变量传递给自定义 ggplot 函数中的参数

最终目标是参数化参数(本例中为

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

r ggplot2 nse
1个回答
0
投票

问题是您希望函数能够以两种截然不同的方式处理参数:它应该能够将不带引号的列名直接作为符号传递,但有时并且没有特定的指令也应该意识到传递的符号不是列名,而是代表调用环境中变量的符号,应对其进行求值并将其从字符串转换为符号。

您需要编写条件代码来识别用户可能的意图并为其生成适当的符号。

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)

© www.soinside.com 2019 - 2024. All rights reserved.