Home > Software engineering >  Make grouped facets the same size in ggplot, accounting for number of facets per group
Make grouped facets the same size in ggplot, accounting for number of facets per group

Time:03-19

I'm working on a problem where I want to create many plots based on some grouping vars. Some of these groups have many values I want to facet, while others only have a few. I want to display all of the facets to be the same size.
In this reprex, the 8 cyl group only has 2 facets while the others have 3. I want the 2 facets in the 8 cyl group to be the same size as facets in the other group, and the space for the 3rd missing facet to just be blank.

library(tidyverse)

for(i in unique(mtcars$cyl)){
  sub_data <- filter(mtcars, cyl == i)
  
  p <- ggplot(sub_data, aes(wt, drat))  
    geom_point()  
    facet_wrap(~gear)  
    labs(title = paste(i, "cyl"))
  print(p)
}

CodePudding user response:

One option would be ggh4x::facet_manual which allows to add blank panels to a plot. For each of your plots you could specify a design which could be filled with blank panels so that each plot has the same number of panels.

library(ggplot2)
library(dplyr)
library(ggh4x)

# Maximum number of panels
nmax <- max(tapply(mtcars$gear, mtcars$cyl, n_distinct))

for(i in unique(mtcars$cyl)){
  sub_data <- filter(mtcars, cyl == i)
  # Number of panels for plot i
  ngear <- n_distinct(sub_data$gear)
  # Create design
  design = paste(c(LETTERS[seq(ngear)], rep("#", nmax - ngear)), collapse = "")
  print(design)
  p <- ggplot(sub_data, aes(wt, drat))  
    geom_point()  
    facet_manual(~gear, design = design, trim_blank = FALSE)  
    labs(title = paste(i, "cyl"))
  print(p)
}
#> [1] "ABC"

#> [1] "ABC"

#> [1] "AB#"

CodePudding user response:

I used @stefan 's advice to look into ggh4x, but ended up ditched design and just used facet_wrap2() and specified rows and columns. The data I am using this on was going to have up to 20 facets so using facet_wrap2 made more sense and avoided the need of building a function to robustly declare the design.

Without the loop it looks like this.

library(tidyverse)
library(ggh4x)

p <- ggplot(mpg, aes(displ, hwy, colour = as.factor(cyl)))   geom_point()  
  labs(x = "Engine displacement", y = "Highway miles per gallon")  
  guides(colour = "none")

p   facet_wrap2(vars(class), nrow = 3, ncol = 4, trim_blank = FALSE)

I was confused for a bit but then embraced the trim blank argument.

You can check out the final product for my project here if you want.

  • Related