我想创建一个“就像”ggplot2
的{{1}}函数一样的函数。我的简单尝试因“找不到对象”错误而失败:
aes()
实施library(ggplot2)
data <- data.frame(a=1:5, b=1:5)
# Works
ggplot(data) + geom_point() + aes(x=a, y=b)
my.aes <- function(x, y) { aes(x=x, y=y) }
# Fails with "Error in eval(expr, envir, enclos) : object 'x' not found"
ggplot(data) + geom_point() + my.aes(x=a, y=b)
的正确方法是什么?这是用于封装和代码重用。
也许这是相关的,我只是看不到如何: How to write an R function that evaluates an expression within a data-frame
答案 0 :(得分:3)
键入aes
,不带任何括号或参数,看看它在做什么:
function (x, y, ...)
{
aes <- structure(as.list(match.call()[-1]), class = "uneval")
rename_aes(aes)
}
它在没有评估它们的情况下获取其参数的名称。它基本上保存了以后的名称,因此它可以在您尝试绘制的数据框的上下文中评估它们(这就是您的错误消息抱怨eval
的原因)。因此,当您在my.aes(x=a, y=b)
构造中加入ggplot
时,它会在x
中寻找data
- 因为x
未在aes(x=x, y=y)
中进行评估。
另一种思考aes
中发生的事情的方法就像是
my.aes <- function(x, y) {
ans <- list(x = substitute(x), y = substitute(y))
class(ans) <- "uneval"
ans
}
应该适用于上面的示例,但请参阅plyr::.
中的注释(使用与match.call()[-1]
相同的aes
范例):
类似的技巧可以用替代品来执行,但是当功能时 可以通过多种方式调用它变得越来越棘手 确保从正确的帧中提取值。 替代技巧也使得难以对抗 引用类提供的函数使用它们 as.quoted.character将字符串转换为适当的数据 结构
如果您希望my.aes
自己调用aes
,可能会这样:
my.aes <- function(x,y) {
do.call(aes, as.list(match.call()[-1]))
}
RomanLuštrik指出的aes_string
函数示例:
my.aes <- function(x,y) {
aes_string(x = x, y = y)
}
但在这种情况下,您需要将通话更改为my.aes("a", "b")
。