通过另一个函数将数据和列名传递给ggplot

时间:2015-12-04 20:46:17

标签: r function ggplot2 environment aesthetics

我会跳过一个例子,然后评论:

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(续,AES(X =值,Y =变量,颜色=基团))+ 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不会采用&#34; data =&#34;参数所以我不能使用facet_grid(data = data,。〜ser)来解决这个问题。我不知道如何从这里开始。

这是一个非常简单的例子,但长期目标是我可以为我办公室里的非R文化人员提供一个功能并说出&#34;给它你的数据框名称,列名和你要拆分的列,它会为你制作漂亮的情节&#34;。它也将变得更加复杂,具有非常自定义的主题,这与我遇到的问题无关。

2 个答案:

答案 0 :(得分:1)

您可以使用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将字符串解析为公式。

答案 1 :(得分:0)

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

eval

enter image description here

要了解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()

reprex package(v0.2.1)于2019-01-10创建


或者,另一种解决方法,但是这次将带引号的列名传递给自定义绘图功能是使用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

get()