0

I am creating a function that uses a forloop to create and return a list of ggplots. When I try to view any of the returned plots, e.g. by calling plots["aClass_20_30"], I get:

Error: StatBin requires a continuous x variable: the x variable is discrete. Perhaps you want stat="count"?

However, if I create one of the plots outside the forloop, as below, it shows up just fine because the variable in question, myVar, IS continuous:

tpp %>%
  filter(risk_class == "aClass", age_buckets=="20_30") %>% 
  ggplot(aes(x=myVar)) +
  geom_area(stat='bin') +
  labs(title = paste("aClass", "20_30", sep="_"))

This is the function:

plot_fixed_age_class_against <- function(variable) {

  temp <- tpp %>% 
    select_('age_buckets', 'rclass', variable) %>% 
    filter(!is.na(rclass))

  plots <- vector("list", 48)

  for (class in unique(temp$rclass)) {
    for (age in unique(temp$age_buckets)) {

      print(paste(class, age, sep="_"))

      plots[[paste(class, age, sep="_")]] <- 
        temp %>%
        filter(rclass == class, age_buckets==age) %>% 
        ggplot(aes(x=variable)) +
          geom_area(stat='bin') +
          labs(title = paste(class, age, sep="_"))
    }
  }
  #print(plots)

  return(plots)
}

and I call it using plots <- plot_fixed_age_class_against("myVar")

If I change bin to count within the forloop, the graphs show up but there is nothing plotted on them. However, using bin outside the forloop, as above, works perfectly. myVar is numeric.

dario
  • 6,415
  • 2
  • 12
  • 26
user699290
  • 41
  • 1
  • 4
  • Due to it's usage of [NSE](https://cran.r-project.org/web/packages/lazyeval/vignettes/lazyeval.html) it's always tricky to use ggplot2 (and other popular packages) functions in custom functions. ggplot thinks you want the character string "myVar" as x-axis, which is of course discrete. – dario Feb 20 '20 at 18:43

2 Answers2

1

You can use aes_string to get ggplot2 to play nice with string arguments:

library(ggplot2)

f <- function(var) {
  ggplot(mtcars, aes(var)) +
    geom_histogram()
}


f("cyl")

Raises this error:

Error: StatBin requires a continuous x variable: the x variable is discrete. Perhaps you want stat="count"?

But if we use ggplot2s alternative to NSE, aes_string:

f <- function(var) {
  ggplot(mtcars, aes_string(var)) +
    geom_histogram()
}


f("cyl")

The plot is drawn without error.

Edit:

Thanks to @akrun for the reminder that aes_string etc are soft depreciated.

According to the ggplot2 docs is this one of the suggested tidyverse alternatives to aes_string :

But if we use ggplot2s alternative to NSE, aes_string:

  f <- function(var) {

    var <- enquo(var)

    ggplot(mtcars, aes(!!var)) +
      geom_histogram()
  }


  f(cyl)
dario
  • 6,415
  • 2
  • 12
  • 26
1

With the new version of tidyverse, the aes_string would get deprecated. Instead, we can use rlang::sym to convert to symbol and then evaluate

library(ggplot2)
f <- function(var) {
   ggplot(mtcars, aes(!! rlang::sym(var))) +
   geom_histogram()
     }


f("cyl")

Also, if we are passing either quoted or unquoted, one option is to use ensym

f <- function(var) {
   ggplot(mtcars, aes(!! rlang::ensym(var))) +
   geom_histogram()
     }

f("cyl")
f(cyl)
akrun
  • 874,273
  • 37
  • 540
  • 662