1

我想创建一个“就像”函数一样工作ggplot2aes()函数。我卑微的尝试以“找不到对象”错误而失败:

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)

正确的实施方式是my.aes()什么?这是为了封装和代码重用。

也许这是相关的,我只是还没有看到如何: 如何编写一个 R 函数来评估数据框中的表达式

4

1 回答 1

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构造中时,它正在寻找xin 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]))
} 

aes_stringRoman Luštrik 指出的函数示例:

my.aes <- function(x,y) {
    aes_string(x = x, y = y)
}

my.aes("a", "b")但在这种情况下,您需要将呼叫更改为。

于 2013-01-16T08:35:36.000 回答