Home > Mobile >  Free axis along particular facets in facet_grid ggplot
Free axis along particular facets in facet_grid ggplot

Time:01-27

I am trying to do 2 things:

First and most important is to somehow get the y axis to vary by the outcome_type2 variable, since they all have fairly different ranges. So the "C" have their own axis range, the "Z" have their own axis range, and the "SS" have their own axis range.

Then the secondary thing would be to somehow adjust the spacing of columns, so that there's a bit of space by those same groups--the 3 "C" columns would be close together, with a bit of extra white space between them and the "Z", then same between "Z" and "SS". Just to differentiate a little more between those three groups.

I tried tinkering with faceting on outcome_type2 instead of outcome_type but to no avail.

This is current base code, which technically works fine, but as you'll see, having them all use the same Y axis really swamps the "Z" and "SS" panels.

ggplot(dtest, aes(x = var2, y = avg2, fill = var2))  
  geom_bar(stat = "identity",
           width = 1)  
  facet_grid(wave ~ forcats::fct_relevel(outcome_type, "CT", "CI", "CE", "FZ", "MZ", "PSS", "CSS"),
             scales = "free_y",
             space = "free_y")  
  theme_minimal()  
  theme(legend.position = "none")
dtest <- structure(list(outcome_type = c("CT", "CT", "CT", "CI", "CI", 
"CI", "CE", "CE", "CE", "FZ", "FZ", "MZ", "MZ", "PSS", "PSS", 
"CSS", "CSS", "CT", "CT", "CT", "CI", "CI", "CI", "CE", "CE", 
"CE", "FZ", "FZ", "MZ", "MZ", "PSS", "PSS", "CSS", "CSS"), wave = c("Wave 1", 
"Wave 2", "Wave 3", "Wave 1", "Wave 2", "Wave 3", "Wave 1", "Wave 2", 
"Wave 3", "Wave 2", "Wave 3", "Wave 2", "Wave 3", "Wave 1", "Wave 3", 
"Wave 1", "Wave 3", "Wave 1", "Wave 2", "Wave 3", "Wave 1", "Wave 2", 
"Wave 3", "Wave 1", "Wave 2", "Wave 3", "Wave 2", "Wave 3", "Wave 2", 
"Wave 3", "Wave 1", "Wave 3", "Wave 1", "Wave 3"), var2 = c("Skipped", 
"Skipped", "Skipped", "Skipped", "Skipped", "Skipped", "Skipped", 
"Skipped", "Skipped", "Skipped", "Skipped", "Skipped", "Skipped", 
"Skipped", "Skipped", "Skipped", "Skipped", "Attended", "Attended", 
"Attended", "Attended", "Attended", "Attended", "Attended", "Attended", 
"Attended", "Attended", "Attended", "Attended", "Attended", "Attended", 
"Attended", "Attended", "Attended"), avg2 = c(30.21, 20.88, 25.43, 
7.68, 8.26, 7.89, 11.15, 8, 5.99, 1.64, 0.43, 0.6, 0.77, 0.01, 
-0.09, -0.2, -0.01, 24.01, 19.98, 29.04, 9.82, 12.41, 12.99, 
14.35, 11.01, 10, 2.36, 2.3, 1.51, 0.91, -0.23, -0.35, -0.17, 
-0.14), outcome_type2 = c("C", "C", "C", "C", "C", "C", "C", 
"C", "C", "Z", "Z", "Z", "Z", "SS", "SS", "SS", "SS", "C", "C", 
"C", "C", "C", "C", "C", "C", "C", "Z", "Z", "Z", "Z", "SS", 
"SS", "SS", "SS")), class = c("spec_tbl_df", "tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -34L), spec = structure(list(
    cols = list(outcome_type = structure(list(), class = c("collector_character", 
    "collector")), wave = structure(list(), class = c("collector_character", 
    "collector")), var2 = structure(list(), class = c("collector_character", 
    "collector")), avg2 = structure(list(), class = c("collector_double", 
    "collector")), outcome_type2 = structure(list(), class = c("collector_character", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1L), class = "col_spec"))

enter image description here

CodePudding user response:

One option would be to create separate plots for each group of panels and glue them together using patchwork. Doing so you get "free" scale for each group of panels automatically and also have one (and only one) axis for each panel group.

To this end first add a group column to your data which could be used to split your dataset by facet panel group. Additionally, for convenience I use a plotting function which also removes the y axis strip texts for the first two groups of panels and as an important step completes each dataset so that all combinations of wave, outcome_type and var2 are present in each sub-dataset.

library(ggplot2)
library(patchwork)
library(magrittr)

dtest$group <- dplyr::case_when(
  grepl("SS$", dtest$outcome_type) ~ "SS",
  grepl("Z$", dtest$outcome_type) ~ "Z",
  TRUE ~ "C"
)
dtest$group <- factor(dtest$group, c("C", "Z", "SS"))

plot_fun <- function(.data) {
  remove_facet <- if (unique(.data$group) %in% c("C", "Z")) {
    theme(strip.text.y = element_blank())
  }

  .data$outcome_type <- forcats::fct_relevel(
    .data$outcome_type,
    "CT", "CI", "CE", "FZ", "MZ", "PSS", "CSS"
  )

  .data %>%
    tidyr::complete(outcome_type, wave = unique(dtest$wave), var2) %>%
    ggplot(aes(x = var2, y = avg2, fill = var2))  
    geom_bar(
      stat = "identity",
      width = 1
    )  
    facet_grid(wave ~ outcome_type)  
    theme_minimal()  
    theme(legend.position = "none")  
    remove_facet
}

dtest_split <- split(dtest, dtest$group)

lapply(dtest_split, plot_fun) %>%
  wrap_plots()  
  plot_layout(widths = c(3, 2, 2)) &
  labs(x = NULL, y = NULL)
#> Warning: 4 unknown levels in `f`: FZ, MZ, PSS, and CSS
#> Warning: 5 unknown levels in `f`: CT, CI, CE, PSS, and CSS
#> Warning: 5 unknown levels in `f`: CT, CI, CE, FZ, and MZ
#> Warning: Removed 4 rows containing missing values (`position_stack()`).
#> Removed 4 rows containing missing values (`position_stack()`).

Created on 2023-01-26 with enter image description here

  • Related