【问题标题】:Passing data and column names to ggplot via another function通过另一个函数将数据和列名传递给 ggplot
【发布时间】:2016-03-09 21:43:06
【问题描述】:

我会直接跳到一个例子并在后面评论:

cont <- data.frame(value = c(1:20),variable = c(1:20,(1:20)^1.5,(1:20)^2),group=rep(c(1,2,3),each=20))

   value   variable group
1       1  1.000000     1
2       2  2.000000     1
3       3  3.000000     1
#... etc.

#ser is shorthand for "series".
plot_scat <- function(data,x,y,ser) {
        ggplot(data,aes(x=x,y=y,color=factor(ser)))+geom_point()
}

plot_scat(cont,value,variable,group)
#This gives the error:
#Error in eval(expr,envir,enclose) : object 'x' not found

现在,我知道 ggplot2 有一个已知错误,其中 aes() 只会在全局环境中查看,而不是在本地环境中查看。听从Use of ggplot() within another function in R的建议,我尝试了另一条路线。

plot_scat <- function(data,x,y,ser) {
        #environment=environment() added
        ggplot(data,aes(x=x,y=y,color=factor(ser)),environment=environment())+geom_point()
}

plot_scat(cont,value,variable,group)
#This gives the error:
#Error in eval(expr,envir,enclos) : object 'value' not found
#In addition: Warning message:
#In eval(expr,envir,enclos) : restarting interrupted promise evaluation

我不知道最后一行是什么意思。如果我打电话: ggplot(cont,aes(x=value,y=variable,color=group))+geom_point()

我得到了你所期望的图表。在命令行中,aes() 正在 ggplot() 中查找变量名称,但它不在函数调用中执行此操作。所以我试图改变我的电话:

plot_scat(cont,cont$value,cont$variable,cont$group)

这让我得到了我想要的。所以我添加了下一层复杂性:

plot_scat <- function(data,x,y,ser) {
        #added facet_grid
        ggplot(data,aes(x=x,y=y,color=factor(ser)),environment=environment())+geom_point()+
        facet_grid(.~ser)
}

plot_scat(cont,cont$value,cont$variable,cont$group)
#This gives the error:
#Error in layout_base(data, cols, drop = drop):
#   At least one layer must contain all variables used for facetting

我对此的想法是 ser 实际上是 cont$group,它可以在 aes() 中使用,但是当传递给 facet_grid 现在是一个单列数据框,没有关于值和变量的信息。根据帮助页面, facet_grid 不采用“data =”参数,所以我不能使用 facet_grid(data=data,.~ser) 来解决这个问题。我不知道如何从这里开始。

这是一个非常简单的例子,但长期目标是有一个功能,我可以在我的办公室里给非 R 识字的人说“给它你的数据框名称、列名和你想要的列分开,它会为你制作漂亮的情节”。它也会变得更加复杂,具有非常定制的主题,这与我遇到的问题无关。

【问题讨论】:

    标签: r function ggplot2 environment aesthetics


    【解决方案1】:

    如果您不想将变量(列名)作为字符串/引用传递,那么我尝试的一种方法(另见here)是使用match.call()eval。它也适用于刻面(如您的情况):

    library(ggplot2)
    
    cont <- data.frame( value = c(1:20),
                        variable = c(1:20, (1:20) ^ 1.5, (1:20) ^ 2),
                        group = rep(c(1, 2, 3), each = 20))
    
    
    plot_scat <- function(data, x, y, ser) {
        arg <- match.call()
        ggplot(data, aes(x = eval(arg$x),
                         y = eval(arg$y),
                         color = factor(eval(arg$ser)))) +
            geom_point() +
            facet_grid(. ~ eval(arg$ser))
    }
    
    # Call your custom function without quoting the variables
    plot_scat(data = cont, x = value, y = variable, ser = group)
    

    要了解match.call() 的作用,可以尝试运行以下代码:

    plot_scat <- function(data, x, y, ser) {
      str(as.list(match.call()))
    }
    plot_scat(cont, value, variable, group)
    #> List of 5
    #>  $     : symbol plot_scat
    #>  $ data: symbol cont
    #>  $ x   : symbol value
    #>  $ y   : symbol variable
    #>  $ ser : symbol group
    

    reprex package (v0.2.1) 于 2019 年 1 月 10 日创建


    或者,另一种解决方法,但这次将引用的列名传递给自定义绘图函数使用get()

    plot_scat <- function(data, x, y, ser) {
        ggplot(data, aes(x = get(x),
                         y = get(y),
                         color = factor(get(ser)))) +
          geom_point() +
          facet_grid(. ~ get(ser))
      }
    
    plot_scat(data = cont, x = "value", y = "variable", ser = "group")
    

    【讨论】:

      【解决方案2】:

      您可以使用 aes_string() 代替 aes() 并将列名作为字符串传递。

      plot_scat <- function(data,x,y,ser) {
      ser_col = paste("factor(",ser,")")
      ggplot(data,aes_string(x=x,y=y,col=ser_col))+geom_point()+facet_grid(as.formula(sprintf('~%s',ser)))
      }
      
      plot_scat(cont,"value","variable","group") 
      

      facet_grid 需要公式,因此您可以使用 as.formula 将字符串解析为公式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-22
        • 2018-08-05
        • 1970-01-01
        • 2019-10-09
        • 2019-07-25
        相关资源
        最近更新 更多