ggplot is not working properly inside a function despite working outside it - R

debugging, function, ggplot2, r

Solution

Aside from using variable names, there is an issue with scope. GGPlot carries out non-standard evaluation in the global environment, so anything defined in your function is not directly accessible, except for the "data" argument since that one is passed explicitly and not through non-standard evaluation. So one work around to this problem is to add your variable to the data argument. I've created an example that I think mimics your problem, but since I don't have your data it's not identical:

gg_fun <- function() {
  data <- data.frame(a=1:10, b=1:10)
  clr <- rep(c("a", "b"), 5)
  ggplot(data, aes(x=a, y=b, color=clr)) + geom_point()
}
gg_fun()
# Error in eval(expr, envir, enclos) : object 'clr' not found
gg_fun <- function() {
  data <- data.frame(a=1:10, b=1:10)
  clr <- rep(c("a", "b"), 5)
  data$clr <- clr
  ggplot(data, aes(x=a, y=b, color=clr)) + geom_point()
}
gg_fun() # works

In your case, you need to add `TimeVector` to `Timesubset` (trivial), and then use the unquoted `aes` syntax:

ggplot(Timesubset, aes(x=TimeVector, y=Statusint)) ...

Problem

I am trying to create a function that takes in 2 parameters & outputs the appropriate ggplot for them. The code works perfectly manually, but somehow I cannot make it work inside a function wrapper. The error returned is ``` Error in eval(expr, envir, enclos) : object 'TimeVector' not found ``` I try to correct for that by coercing the objects not found, which are added to ggplot, as strings. This in turn creates different trouble in form of ``` Error: Discrete value supplied to continuous scale ``` Removing the scale_x_continuous(breaks=0:24) fixes that second error, but outputs an empty graph, suggesting that ggplot is not fed with any data at all. The data is a large data frame of observations of traffic density grouped by time. It looks like this: ``` ID Road Status Time Statusint Day Months Year Weekday 1 Me7war To Sheikh Zayid Orange 2012-10-01 00:03:00 3 1 October 12 Monday 1 Me7war To Sheikh Zayid Green 2012-10-01 05:00:00 2 1 October 12 Monday 1 Me7war To Sheikh Zayid Yellow 2012-10-01 05:24:00 5 1 October 12 Monday ``` I am trying to plot the "Statusint" variable, short for status integer ranging from 1 (good traffic) to 5 (Terrible traffic) against the "Time" variable. "Time" is formatted as Posix, so I create a numeric vector called "TimeVector" for the sole purpose of plotting against in ggplot. The function is as follows: ``` Plotroad <- function( roadID , Day ) { *** Working Code *** else { ### THE PROBLEM CODE: Everything below works manually, but returns an error in the function Roadsubset <- October[October$ID == as.numeric(roadID), ] Timesubset <- subset(Roadsubset, format(Roadsubset$Time,'%d') == "Day" ) TimeVector <- as.numeric(gsub(":" , "." , strftime(Timesubset$Time, format="%H:%M"))) ggplot(Timesubset, aes( x = "TimeVector", y = "Timesubset$Statusint")) + geom_point() + stat_smooth() + scale_x_continuous(breaks=0:24) ### The working code: Roadsubset <- October[October$ID == as.numeric(roadID), ] Timesubset <- subset(Roadsubset, subset = Roadsubset$Day == as.integer(Date) ) TimeVector <- as.numeric(gsub(":" , "." , strftime(Timesubset$Time, format="%H:%M"))) Timesubset$timevector <- TimeVector print(ggplot( data = Timesubset, aes_string( x = "timevector" , y = "Statusint" )) + geom_point() + stat_smooth() + scale_x_continuous(breaks=0:24) + labs(list(title = as.character(Timesubset$Road[1]) , x = "Time of Day", y = "Status"))) } } ``` I have seen some advice suggesting using print, as ggplot is invoked not in the command line. This, however does not fix the aforementioned errors. This is my first post to stack overflow, so please point out how I can better format questions for the future, if in need. Thanks.

Original source

Related problems