【问题标题】:How to define a function that invokes ggplot2 functions and takes a variable name among its arguments?如何定义一个调用 ggplot2 函数并在其参数中采用变量名的函数?
【发布时间】:2020-02-13 20:44:49
【问题描述】:

举个例子,假设我有这个sn-p的代码:

binwidth <- 0.01
my.histogram <- ggplot(my.data, aes(x = foo, fill = type)) +
                geom_histogram(binwidth = binwidth,
                               aes(y = ..density..),
                               position = "identity",
                               alpha = 0.5) +
                lims(x = c(0 - binwidth, 1 + binwidth), y = c(0, 100)) +
                labs(x = "foo", y = "density")

此外,假设my.data 除了foo 之外还有许多其他列,可以使用几乎相同的代码进行绘制。因此,我想定义一个辅助函数make.histogram,这样我就可以将上面的赋值替换为:

my.histogram <- make.histogram(foo, bindwidth = 0.01)

实际上,这对我来说有点奇怪。 R会抱怨foo没有定义吗?也许电话应该是这样的:

my.histogram <- make.histogram("foo", binwidth = 0.01)

尽管如此,如何定义make.histogram

就本问题而言,make.histogram 可以将my.data 视为全局变量。

另外,请注意在上面的 sn-p 中,foo 出现了两次,一次(作为变量)在第一个 aes 调用中作为 x 参数,一次(作为字符串)作为 @ labs 调用中的 987654335@ 参数。换句话说,make.histogram 函数需要以某种方式将其第一个参数中指定的列转换为变量名和字符串。

【问题讨论】:

  • 您可以使用 R 的非标准评估功能来做到这一点。 Hadley Wickham 的 Advanced R 书中很好地描述了它们的工作原理:adv-r.had.co.nz/Computing-on-the-language.html
  • @andrew.punnett:感谢您的指点!我根据从中学到的知识发布了答案。
  • 希望我没有带你走上黑暗的道路!
  • @andrew.punnett:哦,天黑了,好吧! :)

标签: r ggplot2


【解决方案1】:

不确定是否理解您的问题。

为什么不能使用aes_string() 并定义如下函数?

make.histogram <- function(variable) { 
  p <- ggplot(my.data, aes_string(x = variable, fill = "type")) + (...) + xlab(variable)
  print(p)
}

【讨论】:

    【解决方案2】:

    由于 ggplot 是 tidyverse 的一部分,我认为 tidyeval 会派上用场:

    make.histogram <- function(var = "foo", bindwith = 0.01) {
            varName <- as.name(var)
            enquo_varName <- enquo(varName)
            ggplot(my.data, aes(x = !!enquo_varName, fill = type)) +
            ...
            labs(x = var)
    }
    

    基本上,使用as.name(),我们会生成一个匹配var 的名称对象(这里的var 是一个类似“foo”的字符串)。然后,在Programming with dplyr 之后,我们使用enquo() 来查看该名称并将关联的值作为quosure 返回。然后可以使用 !!ggplot() 调用中取消引用此 quosure。

    【讨论】:

      【解决方案3】:

      阅读@andrew.punnett 在他的评论中链接的材料后,编写所需的函数非常容易:

      make.histogram <- function(column.name, binwidth = 0.02) {
      
          base.aes <- eval(substitute(aes(x = column.name, fill = type)))
          x.label <- deparse(substitute(column.name))
      
          ggplot(my.data, base.aes) +
          geom_histogram(binwidth = binwidth,
                         aes(y = ..density..),
                         position = "identity",
                         alpha = 0.5) +
          lims(x = c(0 - binwidth, 1 + binwidth), y = c(0, 100)) +
          labs(x = x.label, y = "density")
      
      }
      
      my.histogram <- make.histogram(foo, binwidth = 0.01)
      

      此解决方案的好处在于其通用性:它仅依赖于基本 R 函数(substituteevaldeparse),因此它可以轻松移植到 ggplot2 上下文之外的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-21
        • 2019-03-11
        • 2017-11-14
        • 1970-01-01
        • 1970-01-01
        • 2022-06-15
        • 2019-04-11
        相关资源
        最近更新 更多