Type aes
without any parentheses or arguments to see what it's doing:
function (x, y, ...)
{
aes <- structure(as.list(match.call()[-1]), class = "uneval")
rename_aes(aes)
}
It takes the name of its arguments without evaluating them. It's basically saving the names for later so it can evaluate them in the context of the data frame you're trying to plot (that's why your error message is complaining about eval
). So when you include my.aes(x=a, y=b)
in your ggplot
construction, it's looking for x
in data
--because x
was not evaluated in aes(x=x, y=y)
.
An alternate way of thinking about what's going on in aes
is something like
my.aes <- function(x, y) {
ans <- list(x = substitute(x), y = substitute(y))
class(ans) <- "uneval"
ans
}
which should work in the example above, but see the note in plyr::.
(which uses the same match.call()[-1]
paradigm as aes
):
Similar tricks can be performed with substitute, but when functions
can be called in multiple ways it becomes increasingly tricky to
ensure that the values are extracted from the correct frame.
Substitute tricks also make it difficult to program against the
functions that use them, while the quoted class provides
as.quoted.character to convert strings to the appropriate data
structure.
If you want my.aes
to call aes
itself, perhaps something like:
my.aes <- function(x,y) {
do.call(aes, as.list(match.call()[-1]))
}
Example with the aes_string
function pointed out by Roman Luštrik:
my.aes <- function(x,y) {
aes_string(x = x, y = y)
}
but you would need to change your call to my.aes("a", "b")
in this case.