Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Place strip panels on opposite sides of plot

Some journals require that figures with several graphs have each of the plots lettered. I'm trying to do the same with facet_wrap in ggplot2 because I've organized the data in such a way that covariates for all my explanatory variables are in one column and the grouping variables for the covariates are in another column.

I followed the instructions here to give the effect that the x-axis label is different for each plot (when it's really a panel).

But I still need labels for each plot (column figure.letters) in the figure, preferably in the top-left hand corner. I've attempted to add it in the facet_wrap formula, so now each plot has two strip panels.

require(ggplot2)
my.df <- data.frame(
  param = rep(c('Distance (km)', 'Energy (j)', 'Girth (m)', 'Height (cm)', 'Incline (degrees)'), each = 20),
  explanatory = rnorm(100, 0, 1),
  response = rnorm(100, 0, 1),
  figure.letter = rep(LETTERS[1:5], each = 20)
)

ggplot(my.df, aes(x = explanatory, y = response)) +
  geom_point() +
  facet_wrap(. ~ param + figure.letter, strip.position = 'bottom') +
  theme_bw() +
  theme(
    strip.placement = 'bottom',
    strip.background = element_blank()
  )

enter image description here

There are a lot of really good answers here, but they're more geared towards moving all the strip panels to the top and then left-justifying the panel text. I'm looking to separate the two strip panels so that the figure letter panel sits on top and is left-justified while the param strip panel remains at the bottom.

I'm also hoping to avoid writing code for several plots and then use patchwork to get the figure labels.

Is there a way to take the strip panel for the figure.letter and move it to the top while keeping the strip panel for param at the bottom?

like image 890
Lalochezia Avatar asked Nov 29 '25 22:11

Lalochezia


1 Answers

You can use geom_text() to place labels outside the plot area if you turn off clipping in coord_cartesian() and use the same fixed axis limits for all facets.

If you have different axis limits for different facets, then the patchwork route will likely be your only option.

require(ggplot2)
#> Loading required package: ggplot2

set.seed(1234)
my.df <- data.frame(
  param = rep(c('Distance (km)', 'Energy (j)', 'Girth (m)', 'Height (cm)', 'Incline (degrees)'), each = 20),
  explanatory = rnorm(100, 0, 1),
  response = rnorm(100, 0, 1)
)

df.label <- data.frame(
  param = unique(my.df$param),
  x = -2.8,
  y = 3.6,
  figure.letter = LETTERS[1:5]
)

ggplot(my.df, aes(x = explanatory, y = response)) +
  geom_point() +
  geom_text(
    data = df.label, aes(x = x, y = y, label = figure.letter),
    hjust = 0, vjust = 0
  ) +
  facet_wrap(. ~ param, strip.position = 'bottom') +
  coord_cartesian(
    xlim = c(-2.8, 2.8),
    ylim = c(-3.3, 3.3),
    expand = FALSE,
    clip = "off"
  ) +
  theme_bw() +
  theme(
    strip.placement = 'bottom',
    strip.background = element_blank(),
    plot.margin = margin(16.5, 5.5, 5.5, 5.5))
#> Warning: Suppressing axis rendering when strip.position = 'bottom' and
#> strip.placement == 'outside'

Created on 2020-01-05 by the reprex package (v0.3.0)

like image 71
Claus Wilke Avatar answered Dec 02 '25 14:12

Claus Wilke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!