Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of ggplot() within another function in R

Tags:

r

ggplot2

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! :) )

like image 317
trev Avatar asked Feb 24 '11 15:02

trev


People also ask

What does ggplot () do?

ggplot() initializes a ggplot object. It can be used to declare the input data frame for a graphic and to specify the set of plot aesthetics intended to be common throughout all subsequent layers unless specifically overridden.

What does %>% do in ggplot?

%>% is a pipe operator reexported from the magrittr package. Start by reading the vignette. Adding things to a ggplot changes the object that gets created. The print method of ggplot draws an appropriate plot depending upon the contents of the variable.

Can you filter within ggplot?

ggplot2 allows you to do data manipulation, such as filtering or slicing, within the data argument.


2 Answers

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.

testplot <- function(meansdf) {   p <- ggplot(meansdf,                aes(fill = condition,                   y = means,                   x = condition))   p + geom_bar(position = "dodge", stat = "identity") } 

This works, because the variables referred to in aes are looked for either in the global environment or in the data frame passed to ggplot. That is also the reason why your example code - using meansdf$condition etc. - did not work: meansdf is neither available in the global environment, nor is it available inside the data frame passed to ggplot, which is meansdf 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:

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") } 

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 to ggplot. Here's what that would look like for the above example:

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) 
like image 194
jhin Avatar answered Oct 09 '22 03:10

jhin


The "proper" way to use ggplot programmatically is to use aes_string() instead of aes() 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 use aes_string(), with the columns needed as characters.

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") } 
like image 36
Gregor Thomas Avatar answered Oct 09 '22 03:10

Gregor Thomas