Marc Tulla
Marc Tulla

Reputation: 1771

Passing ggplot through a function and referencing an argument

I'm using ggplot2 within a function and trying to create average lines for the y-axis. I'm running into trouble seemingly because the variable that defines the y-axis is one of the function args, and I can't call it directly within ggplot.

library(ggplot2)


west <- data.frame(
  spend = sample(50:100,50,replace=T),
  trials = sample(100:200,50,replace=T),
  courts = sample(25:50,50,replace=T),
  country = sample(c("usa","canada","uk"),50,replace = T)
)

Here's a basic version of the function I'm working with:

ggfun <- function(data, xvar, yvar) {

  newplot <- ggplot(data=west, aes_string(x=xvar, y=yvar)) +
    geom_point(shape=21, fill="blue") + 

  newplot      
}

and calling that as below works:

ggfun(west, "spend", "trials")

But when I try to add in geom_hline, I get an error:

ggfun <- function(data, xvar, yvar) {

  newplot <- ggplot(data=west, aes_string(x=xvar, y=yvar)) +
    geom_point(shape=21, fill="blue") + 
    geom_hline(yintercept=mean(yvar))

  newplot  
}

ggfun(west, "spend", "trials")

Warning messages:
1: In mean.default(data$yvar) :
  argument is not numeric or logical: returning NA
2: Removed 1 rows containing missing values (geom_hline).

Is it not possible to call data this way within a function using ggplot?

Upvotes: 1

Views: 550

Answers (2)

GGamba
GGamba

Reputation: 13680

aes_string substitutes the whole string, not just the var. You can create the right string using paste:

library(ggplot2)
west <- data.frame(
  spend = sample(50:100,50,replace=T),
  trials = sample(100:200,50,replace=T),
  courts = sample(25:50,50,replace=T),
  country = sample(c("usa","canada","uk"),50,replace = T)
)
ggfun <- function(data, xvar, yvar) {
  newplot <- ggplot(data=data, aes_string(x=xvar, y=yvar)) +
    geom_point(shape=21, fill="blue") + 
    geom_hline(aes_string(yintercept = paste0('mean(', yvar, ')')))

  newplot  
}
ggfun(west, "spend", "trials")

Upvotes: 1

Gregor Thomas
Gregor Thomas

Reputation: 146224

yvar is a string, it works exactly as if you were doing this, not in a function:

ggplot(mtcars, aes(wt, mpg)) + 
  geom_point() + 
  geom_hline(yintercept = mean("mpg"))
Warning messages:
1: In mean.default("mpg") :
  argument is not numeric or logical: returning NA
2: Removed 1 rows containing missing values (geom_hline). 

I'd recommend pre-computing the mean, that way you can pass a value to the yintercept:

ggfun <- function(data, xvar, yvar) {
  mean_yvar = mean(data[[yvar]])
  newplot <- ggplot(data = west, aes_string(x = xvar, y = yvar)) +
    geom_point(shape=21, fill="blue") + 
    geom_hline(yintercept = mean_yvar)

  newplot  
}

ggfun(west, "spend", "trials")
# works fine

Upvotes: 1

Related Questions