I'm trying to write a simple plot function, using the ggplot2 library. But the call to ggplot doesn't find the function argument.
Consider a data.frame
called means
that stores two conditions and two mean values that I want to plot (condition will appear on the X axis, means on the 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
So it seems that ggplot is calling eval
, which can't find the argument meansdf
. Does anyone know how I can successfully pass the function argument to ggplot?
(Note: Yes I could just call the ggplot function directly, but in the end I hope to make my plot function do more complicated stuff! :) )
Another workaround is to define the aes(...) as a variable of your function :
This just worked fine for me on a similar topic
I don't think you need to include the
meansdf$
part in your function call itself. This seems to work on my machine:to produce:
As Joris and Chase have already correctly answered, standard best practice is to simply omit the
meansdf$
part and directly refer to the data frame columns.This works, because the variables referred to in
aes
are looked for either in the global environment or in the data frame passed toggplot
. That is also the reason why your example code - usingmeansdf$condition
etc. - did not work:meansdf
is neither available in the global environment, nor is it available inside the data frame passed toggplot
, which ismeansdf
itself.The fact that the variables are looked for in the global environment instead of in the calling environment is actually a known bug in ggplot2 that Hadley does not consider fixable at the moment. This leads to problems, if one wishes to use a local variable, say,
scale
, to influence the data used for the plot:A very nice workaround for this case is provided by Winston Chang in the referenced GitHub issue: Explicitly setting the
environment
parameter to the current environment during the call toggplot
. Here's what that would look like for the above example:I just generate new data frame variables with the desired names inside the function:
This is an example of a problem that is discussed earlier. Basically, it comes down to ggplot2 being coded for use in the global environment mainly. In the aes() call, the variables are looked for either in the global environment or within the specified dataframe.
EDIT:
update: After seeing the other answer and updating the ggplot2 package, the code above works. Reason is, as explained in the comments, that ggplot will look for the variables in aes in either the global environment (when the dataframe is specifically added as meandf$... ) or within the mentioned environment.
For this, be sure you work with the latest version of ggplot2.
The "proper" way to useggplot
programmatically is to useaes_string()
instead ofaes()
and use the names of the columns as characters rather than as objects:For more programmatic uses, for example if you wanted users to be able to specify column names for various aesthetics as arguments, or if this function is going in a package that needs to pass
R CMD CHECK
without warnings about variable names without definitions, you can useaes_string()
, with the columns needed as characters.