我正在尝试使用ggplot2库编写一个简单的绘图函数.但是对ggplot的调用没有找到函数参数.
考虑一个存储两个条件和两个我想要绘制的平均值的data.frame
调用means
(条件将出现在X轴上,表示在Y上).
library(ggplot2)
m <- c(13.8, 14.8)
cond <- c(1, 2)
means <- data.frame(means=m, condition=cond)
means
# The output should be:
# means condition
# 1 13.8 1
# 2 14.8 2
testplot <- function(meansdf)
{
p <- ggplot(meansdf, aes(fill=meansdf$condition, y=meansdf$means, x = meansdf$condition))
p + geom_bar(position="dodge", stat="identity")
}
testplot(means)
# This will output the following error:
# Error in eval(expr, envir, enclos) : object 'meansdf' not found
Run Code Online (Sandbox Code Playgroud)
所以似乎ggplot正在调用eval
,它无法找到参数meansdf
.有谁知道如何成功将函数参数传递给ggplot?
(注意:是的我可以直接调用ggplot函数,但最后我希望让我的绘图函数做更复杂的东西!:))
jhi*_*hin 37
由于Joris和Chase已经正确回答,标准的最佳实践是简单地省略该meansdf$
部分并直接引用数据框列.
testplot <- function(meansdf)
{
p <- ggplot(meansdf,
aes(fill = condition,
y = means,
x = condition))
p + geom_bar(position = "dodge", stat = "identity")
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为aes
在全局环境或传递给的数据框中查找引用的变量ggplot
.这也是你的示例代码 - 使用meansdf$condition
等 - 不起作用的原因:meansdf
在全局环境中既不可用,也不在传递给它的数据框内可用ggplot
,这meansdf
本身也是如此.
在全局环境中而不是在调用环境中查找变量这一事实实际上是ggplot2中的一个已知错误,Hadley目前不认为它是可修复的.如果想要使用局部变量scale
来影响用于绘图的数据,这会导致问题:
testplot <- function(meansdf)
{
scale <- 0.5
p <- ggplot(meansdf,
aes(fill = condition,
y = means * scale, # does not work, since scale is not found
x = condition))
p + geom_bar(position = "dodge", stat = "identity")
}
Run Code Online (Sandbox Code Playgroud)
Winston Chang在引用的GitHub问题中提供了一个非常好的解决方法:environment
在调用期间将参数显式设置为当前环境ggplot
.这是上面例子的样子:
testplot <- function(meansdf)
{
scale <- 0.5
p <- ggplot(meansdf,
aes(fill = condition,
y = means * scale,
x = condition),
environment = environment()) # This is the only line changed / added
p + geom_bar(position = "dodge", stat = "identity")
}
## Now, the following works
testplot(means)
Run Code Online (Sandbox Code Playgroud)
Gre*_*gor 30
以ggplot
编程方式使用的"正确"方法是使用aes_string()
而不是aes()
使用列的名称作为字符而不是作为对象:
对于更多编程用途,例如,如果您希望用户能够将各种美学的列名称指定为参数,或者如果此函数在需要传递的包中,R CMD CHECK
而没有关于没有定义的变量名称的警告,则可以使用aes_string()
,作为字符需要的列.
testplot <- function(meansdf, xvar = "condition", yvar = "means",
fillvar = "condition") {
p <- ggplot(meansdf,
aes_string(x = xvar, y= yvar, fill = fillvar)) +
geom_bar(position="dodge", stat="identity")
}
Run Code Online (Sandbox Code Playgroud)
小智 18
这是我在函数环境中定义变量的一个简单技巧(第二行):
FUN <- function(fun.data, fun.y) {
fun.data$fun.y <- fun.data[, fun.y]
ggplot(fun.data, aes(x, fun.y)) +
geom_point() +
scale_y_continuous(fun.y)
}
datas <- data.frame(x = rnorm(100, 0, 1),
y = x + rnorm(100, 2, 2),
z = x + rnorm(100, 5, 10))
FUN(datas, "y")
FUN(datas, "z")
Run Code Online (Sandbox Code Playgroud)
请注意当使用不同的变量或数据集时,y轴标签也会如何变化.
Cha*_*ase 16
我认为您不需要meansdf$
在函数调用中包含该部分.这似乎适用于我的机器:
meansdf <- data.frame(means = c(13.8, 14.8), condition = 1:2)
testplot <- function(meansdf)
{
p <- ggplot(meansdf, aes(fill=condition, y=means, x = condition))
p + geom_bar(position="dodge", stat="identity")
}
testplot(meansdf)
Run Code Online (Sandbox Code Playgroud)
生产:
Jor*_*eys 15
这是前面讨论的问题的一个例子.基本上,它归结为ggplot2主要用于全球环境.在aes()调用中,变量在全局环境中或在指定的数据帧中查找.
library(ggplot2)
means <- data.frame(means=c(13.8,14.8),condition=1:2)
testplot <- function(meansdf)
{
p <- ggplot(meansdf, aes(fill=condition,
y=means, x = condition))
p + geom_bar(position="dodge", stat="identity")
}
Run Code Online (Sandbox Code Playgroud)
编辑:
更新:看到其他答案并更新ggplot2包后,上面的代码工作.正如评论中所解释的那样,原因是ggplot将在全局环境中查找aes中的变量(当数据帧专门添加为meandf $ ...时)或在上述环境中.
为此,请务必使用最新版本的ggplot2.
如果将变量(列名称)传递给不带引号的自定义绘图函数很重要,而函数中使用不同的变量名称,那么我尝试的另一个解决方法是使用match.call()
and eval
(也像这里一样):
library(ggplot2)
meansdf <- data.frame(means = c(13.8, 14.8), condition = 1:2)
testplot <- function(df, x, y) {
arg <- match.call()
scale <- 0.5
p <- ggplot(df, aes(x = eval(arg$x),
y = eval(arg$y) * scale,
fill = eval(arg$x)))
p + geom_bar(position = "dodge", stat = "identity")
}
testplot(meansdf, condition, means)
Run Code Online (Sandbox Code Playgroud)
由reprex 包(v0.2.1)于 2019-01-10 创建
另一种解决方法是将带引号的变量传递给自定义绘图函数,方法是使用get()
:
meansdf <- data.frame(means = c(13.8, 14.8), condition = 1:2)
testplot <- function(df, x, y) {
scale <- 0.5
p <- ggplot(df, aes(x = get(x),
y = get(y) * scale,
fill = get(x)))
p + geom_bar(position = "dodge", stat = "identity")
}
testplot(meansdf, "condition", "means")
Run Code Online (Sandbox Code Playgroud)
由reprex 包(v0.2.1)于 2019-01-10 创建
归档时间: |
|
查看次数: |
53675 次 |
最近记录: |