tastycanofmalk
tastycanofmalk

Reputation: 628

ggplot2 variables within function

Feel I am making a very dumb mistake here.. as I've done this before on another project (maybe luck?)

Goal is to construct several graphs in ggplot via use of a function. I eventually want all the graphs displayed on a single page, etc...

Here is an example of a single ggplot that works:

if (require("ggplot2") == FALSE) install.packages("ggplot2")

data_df = data.frame(matrix(rnorm(200), nrow=20))
time=1:nrow(data_df)

ggplot(data=data_df, aes(x=time, y=data_df[,1])) + 
        geom_point(alpha=1/4) + 
        ggtitle(deparse(substitute(data_df[1])))

Note there are other functions that will be called within this that will change based on the dataframe column called. I followed another working example I had made, but this just gives me an error. I feel like I'm making an elementary mistake but can't put my finger on it!

if (require("ggplot2") == FALSE) install.packages("ggplot2")

data_df = data.frame(matrix(rnorm(200), nrow=20))
time=1:nrow(data_df)

graphit <- function(sample_num){
        ggplot(data=data_df, aes(x=time, y=data_df[,sample_num])) + 
                geom_point(alpha=1/4) + 
                ggtitle(deparse(substitute(data_df[sample_num])))
}

graphit(1)

#Error in `[.data.frame`(data_df, , sample_num) : 
#  object 'sample_num' not found

Thanks for any help.

Upvotes: 2

Views: 2622

Answers (2)

Vlo
Vlo

Reputation: 3188

Can't comment due to rep count. Joran's solution (and advice on ggplot2) is highly recommended.

Here is a highly not recommended hack that will get your code to work. Add this line as the first line of your function.

assign(x = "sample_num", value = sample_num, envir=.GlobalEnv)

Alternative synthax for the same code above is sample_num <<- sample_num.

The issue you are facing is an scoping issue. sample_num exists only within the graphit() environment and is not defined within the ggplot() environment.

Upvotes: 1

joran
joran

Reputation: 173697

You're doing several things wrong.

First, everything specified inside aes() should be columns in your data frame. Do not reference separate vectors, or redundantly call columns via data_df[,1]. The whole point of specifying data = data_df is that then everything inside aes() is evaluated within that data frame.

Second, to write functions to create ggplots on different columns based on arguments, you should be using aes_string so that you can pass the aesthetic mappings as characters explicitly and avoid problems with non-standard evaluation.

Similarly, I would not rely on deparse(substitute()) for the plot title. Use some other variable built into the data frame, or some other data structure.

For instance, I would do something more like this:

data_df = data.frame(matrix(rnorm(200), nrow=20))
time=1:nrow(data_df)
data_df$time <- time

graphit <- function(data,column){
    ggplot(data=data, aes_string(x="time", y=column)) + 
        geom_point(alpha=1/4) + 
        ggtitle(column)
}

graphit(data_df,"X1")

Upvotes: 8

Related Questions