Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot facet wrap variable as an argument in a function

Tags:

r

ggplot2

I'm trying to write a function where one of the arguments is the variable by which to facet wrap.

Minimum reproducible example:

library(tidyverse)
library(ggplot2)

wobble<- matrix(1:9, 3) %>% as_tibble()


wibble_fun <- function(df, var) {
   df %>%
     ggplot(aes(var)) +
     geom_bar() + 
     facet_wrap(~var)
}


wibble_fun(wobble, "V1")

The resulting error:

Error: At least one layer must contain all faceting variables: `var`.
* Plot is missing `var`
* Layer 1 is missing `

Seems like var in facet_wrap(~var) is interpreted as the string 'var' instead of being substituted by "V1", which is the second argument when I call the function.

Is there a way to make this work?

like image 933
ostermann Avatar asked Mar 21 '19 23:03

ostermann


3 Answers

Here's a solution using {{...}} around the variable within the function instead of using sym and unqoting:

library(tidyverse)
library(ggplot2)

wobble<- matrix(1:9, 3) %>% as_tibble()


wibble_fun <- function(df, var) {
   df %>%
     ggplot(aes({{var}})) +
     geom_bar() + 
     facet_wrap(vars({{var}}))
}


wibble_fun(wobble, V1)
like image 56
mgrund Avatar answered Nov 14 '22 22:11

mgrund


I think an easy fix to your problem would be using [[ to pass the column var into your function:

    wibble_fun <- function(df, var) {
     df %>%
     ggplot(aes(df[[var]])) +
     geom_bar() + 
     facet_wrap(~df[[var]])
}


wibble_fun(wobble, "V1")
like image 36
Chuan Avatar answered Nov 14 '22 23:11

Chuan


A different way to do this makes use of Non-Standard Evaluation which, while confusing, is the "official" way to do things like this in the tidyverse.

We use the sym function to convert var from a string into a symbol, then unquote it with !! in the aes.

For the facet_wrap: as marius pointed out in the comments, facet_wrap can accept a string or symbol instead of a formula (made with ~). You can either pass in your symbol x or the string var itself: you'll get the same results.

library(tidyverse)
library(ggplot2)

wobble<- matrix(1:9, 3) %>% as_tibble()


wibble_fun <- function(df, var) {
    x = sym(var)
    df %>%
        ggplot(aes(!!x)) +
        geom_bar() + 
        facet_wrap(x)
}


wibble_fun(wobble, "V1")

Plot

like image 22
divibisan Avatar answered Nov 14 '22 23:11

divibisan