Home > front end >  How to write ggplot wrappers around facet_wrap()?
How to write ggplot wrappers around facet_wrap()?

Time:11-15

Dear R community on SO,

I am trying to create a wrapper function around ggplot2::facet_wrap().

My goal would be to pass a split_by parameter to ggplot2::facet_wrap(), possibly unquoted, as follows:

my_ggplot2_wrapper(my_data, x = some_x_col, y = some_y_col, split_by = another_discrete_var).

split_by would be a column contained in the data I pass to my wrapper.

Below is what I have tried.

Thanks in advance for considering my request.

Other solutions I've tried without success:

  • p ggplot2::facet_wrap(ggplot2::vars(split_by), ncol = 2, nrow = 2)
  • p ggplot2::facet_wrap({{ split_by }}, ncol = 2, nrow = 2)
sessionInfo()
#> R version 4.1.3 (2022-03-10)
#> Platform: x86_64-apple-darwin17.0 (64-bit)
#> Running under: macOS Big Sur/Monterey 10.16
#> 
#> Matrix products: default
#> BLAS:   /opt/R/4.1.3/Resources/lib/libRblas.0.dylib
#> LAPACK: /opt/R/4.1.3/Resources/lib/libRlapack.dylib
#> 
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] withr_2.5.0       digest_0.6.29     R.methodsS3_1.8.2 lifecycle_1.0.2  
#>  [5] magrittr_2.0.3    reprex_2.0.2      evaluate_0.16     highr_0.9        
#>  [9] stringi_1.7.8     rlang_1.0.6       cli_3.4.1         rstudioapi_0.14  
#> [13] fs_1.5.2          R.utils_2.12.1    R.oo_1.25.0       styler_1.8.1     
#> [17] rmarkdown_2.16    tools_4.1.3       stringr_1.4.1     R.cache_0.16.0   
#> [21] glue_1.6.2        purrr_0.3.4       xfun_0.32         yaml_2.3.5       
#> [25] fastmap_1.1.0     compiler_4.1.3    htmltools_0.5.3   knitr_1.40

set.seed(2022)
library(rlang)

ts <- tibble::tibble(
  ds = seq(as.Date("2018-01-01"), as.Date("2019-12-31"), by = "1 day"),
  y = rnorm(length(ds), mean = 50, sd = 10)
)
ts_component <- purrr::map_dfr(
  c("A", "B", "C", "D"),
  ~ dplyr::mutate(ts, component = .x)
)

ts_component
#> # A tibble: 2,920 × 3
#>    ds             y component
#>    <date>     <dbl> <chr>    
#>  1 2018-01-01  59.0 A        
#>  2 2018-01-02  38.3 A        
#>  3 2018-01-03  41.0 A        
#>  4 2018-01-04  35.6 A        
#>  5 2018-01-05  46.7 A        
#>  6 2018-01-06  21.0 A        
#>  7 2018-01-07  39.4 A        
#>  8 2018-01-08  52.8 A        
#>  9 2018-01-09  57.5 A        
#> 10 2018-01-10  52.4 A        
#> # … with 2,910 more rows

my_ggplot2_wrapper <- function(data, x = ds, y = y, split_by = NULL) {
  split_by <- rlang::enquo(split_by)

  p <- ggplot2::ggplot()  
  ggplot2::geom_line(
    data = data,
    ggplot2::aes(x = {{ x }}, y = {{ y }})
  )

  if (!is.null(split_by)) {
    p   ggplot2::facet_wrap(ggplot2::vars(!!split_by), ncol = 2, nrow = 2)
  }

  p
}

# I would expect `split_by` to work and provide four panels named A, B, C, D, instead of a single one.
my_ggplot2_wrapper(data = ts_component, split_by = component)

Created on 2022-11-14 with enter image description here

CodePudding user response:

Hope I understood your properly. If you need to pass a character value and use it as symbol for facetting you can do the following:

library(ggplot2)
library(magrittr)


gg <- function(coln = "carb"){
  mtcars %>% 
  ggplot(aes(cyl, mpg)) 
  geom_bar(stat = "identity")  
  facet_wrap(bquote(~ .(sym(coln)))) 
}

gg("carb")

Character vector with a single element "carb" is passed to ggplot wrapper function and is used by faceting layer. The result is following:

enter image description here

  • Related