SiH
SiH

Reputation: 1546

create a nested facet grid

Here is a sample code for ggplot with facets.

The current code creates a 2 by 4 panel of plots. My most important categorical variable is A. I want to distinctly separate plots based on values of A i.e. 2 sets/nests of 2 by 2 panels based on values of A.

  1. Is it possible to create a common top panel for same values of A.

Thanks

library(tidyverse)

# continuous variables
x <- runif(160)
y <- runif(160)

# 3 categorical variables, each with 2 levels
A <- c(rep(0, 80), rep(1, 80))
b <- c(rep(0, 40), rep(1, 40), rep(0, 40), rep(1, 40))
c <- c(rep(0, 20), rep(1, 20), rep(0, 20), rep(1, 20), 
       rep(0, 20), rep(1, 20), rep(0, 20), rep(1, 20))

# tibble

tbl <- tibble(x, y, A, b, c) %>%
  # rename the categorical variables for better labels in facet panels
  mutate(A = factor(A, levels = c(1, 0), labels = paste0("A = ", c(1, 0)))) %>%
  mutate(b = factor(b, levels = c(1, 0), labels = paste0("b = ", c(1, 0)))) %>%
  mutate(c = factor(c, levels = c(1, 0), labels = paste0("c = ", c(1, 0))))
  

# ggplot
ggplot(data = tbl,
       aes(x = x,
           y = y)) + 
  geom_point() + 
  facet_grid(c ~ A + b) +
  theme_bw() +
  theme(aspect.ratio = 1)

[![enter image description here][1]][1]

Upvotes: 0

Views: 1297

Answers (2)

Ian Campbell
Ian Campbell

Reputation: 24790

Since editing grobs is a bit tricky for the uninitiated, here is how you could implement Allan Cameron's excellent solution provided in this answer.

First, save the plot to a variable.

p <- ggplot(data = tbl,
       aes(x = x,
           y = y)) + 
  geom_point() + 
  facet_grid(c ~ A + b) +
  theme_bw() +
  theme(aspect.ratio = 1)
p

enter image description here Now convert the plot to grob an identify the location of the strips.

library(tidyverse)
library(gtable)
library(grid)
g <- ggplot_gtable(ggplot_build(p))
stript <- grep("strip", g$layout$name)

Then using Allan's code, I modified the variable in the labs and the height a little, but otherwise, his code is totally reusable.

grid_cols <- sort(unique(g$layout[stript,]$l))
t_vals <- rep(sort(unique(g$layout[stript,]$t)), each = length(grid_cols)/2)
l_vals <- rep(grid_cols[seq_along(grid_cols) %% 2 == 1], length = length(t_vals))
r_vals <- rep(grid_cols[seq_along(grid_cols) %% 2 == 0], length = length(t_vals))
labs   <- levels(as.factor(p$data$A))

for(i in seq_along(labs))
{
  filler <- rectGrob(y = 0.72, height = 0.57, gp = gpar(fill = "gray85", col = "black"))
  tg    <- textGrob(label = labs[i], y = 0.75, gp = gpar(cex = 0.8))
  g     <- gtable_add_grob(g, filler, t = t_vals[i], l = l_vals[i], r = r_vals[i], 
                           name = paste0("filler", i))
  g     <- gtable_add_grob(g, tg, t = t_vals[i], l = l_vals[i], r = r_vals[i], 
                           name = paste0("textlab", i))
}
grid.newpage()
grid.draw(g)

enter image description here

Upvotes: 2

Mario Niepel
Mario Niepel

Reputation: 1165

Does this work four you:

library(patchwork)

P1 <- tbl %>% filter (A == "A = 1") %>%

ggplot(aes(x = x,
          y = y)) + 
    geom_point() + 
    facet_grid(c ~ b) +
    theme_bw() +
    theme(aspect.ratio = 1)

P2 <- tbl %>% filter (A == "A = 0") %>%
    
    ggplot(aes(x = x,
             y = y)) + 
    geom_point() + 
    facet_grid(c ~ b) +
    theme_bw() +
    theme(aspect.ratio = 1)

P1 + P2 

enter image description here

Created on 2021-01-04 by the reprex package (v0.3.0)

Upvotes: 1

Related Questions