how can I use math expressions in ggplot2 facet labels

120 Views Asked by At

In the following plot, I would like to replace "d" by delta, include a per mil symbol at the end, and use superscripts in: d13C, d15N and d34S.I got it when I use a biplot (e.g. plot + ylab(expression(paste(delta^{15}, "N (\u2030)")))). However, in the attached plot, I'm using facet_grid, which may change the way to get it. Here is the script used:

group.violin<-ggplot(group.data, aes(x=Culture2, group = Culture2, y=value)) +
  stat_summary(aes(x = Culture2, y = value, color= Species, group = Species), fun = "mean", 
               geom = "line", lwd = 2, alpha = 0.5)+
  stat_summary(geom="point")+
  geom_violin(aes(x = Culture2, y = value, fill = Species), alpha = 0.4, color = NA)+
  geom_point(aes(x = Culture2, y = value, fill = Species), size = 3, color = "black", pch = 21,
             position = position_jitter(width = 0.05, seed = 12))+
  facet_grid(variable ~ Species, scales = "free_y") +
  xlab("")+ 
  ylab("")+
  theme_classic()+
  theme(strip.background = element_rect(colour = "black", fill = "grey85", size = 0.1),
        panel.border=element_rect(colour="black",size = 0.1, fill = NA),
        panel.spacing = unit(0.3, "lines"),
        axis.text.y = element_text(size = 12, colour = "black"),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        legend.position = "bottom",
        legend.text=element_text(size=12, face="italic"),
        legend.title=element_text(size=12,face="bold"),
        strip.text.x=element_text(size=12,face="bold.italic"),
        strip.text.y=element_text(size=12,face="bold"))

Thank you enter image description here

enter image description here

1

There are 1 best solutions below

3
r2evans On BEST ANSWER

We can use sub to change your variable to be the labels you expect, then add labeller=label_parsed to the call to facet_grid.

Using my sample data (below), original plotting code:

original plot with no plotmath facet labels

group.data |>
  transform(
    variable2 = sub("d([0-9]+)(.*)", "delta^{\\1}*'\\2 (\u2030)'", variable)
  ) |> 
  ggplot(aes(x=Culture2, group = Culture2, y=value)) +
  stat_summary(aes(x = Culture2, y = value, color= Species, group = Species), fun = "mean", 
               geom = "line", lwd = 2, alpha = 0.5)+
  stat_summary(geom="point")+
  geom_violin(aes(x = Culture2, y = value, fill = Species), alpha = 0.4, color = NA)+
  geom_point(aes(x = Culture2, y = value, fill = Species), size = 3, color = "black", pch = 21,
             position = position_jitter(width = 0.05, seed = 12))+
  facet_grid(variable2 ~ Species, scales = "free_y", labeller = label_parsed) +
  xlab("")+ 
  ylab("")+
  theme_classic()+
  theme(strip.background = element_rect(colour = "black", fill = "grey85", size = 0.1),
        panel.border=element_rect(colour="black",size = 0.1, fill = NA),
        panel.spacing = unit(0.3, "lines"),
        axis.text.y = element_text(size = 12, colour = "black"),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        legend.position = "bottom",
        legend.text=element_text(size=12, face="italic"),
        legend.title=element_text(size=12,face="bold"),
        strip.text.x=element_text(size=12,face="bold.italic"),
        strip.text.y=element_text(size=12,face="bold"))
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`
# No summary function supplied, defaulting to `mean_se()`

same plot with plotmath facet labels

Unfortunately, this drops the bold/italic formatting you themed into the facet labels, so we need to be clearer on those. Further, having bold-italic in the facet strips and just italic in the other poses a small problem ... but I'll hack it into place by using plotmath-like "bolditalic(..)" expressions (strings) for everything, and then remove the bold portion of that string for just the legends.

For this step, we'll transform Species as well, then add scale_colour_discrete and _fill_ hacks using scales::label_parse for the labels= argument.

group.data |>
  transform(
    variable2 = sub("d([0-9]+)(.*)", "bold(delta^{\\1}*'\\2 (\u2030)')", variable),
    Species = sprintf("bolditalic(%s)", Species)
  ) |> 
  ggplot(aes(x=Culture2, group = Culture2, y=value)) +
  stat_summary(aes(x = Culture2, y = value, color= Species, group = Species), fun = "mean", 
               geom = "line", lwd = 2, alpha = 0.5)+
  stat_summary(geom="point")+
  geom_violin(aes(x = Culture2, y = value, fill = Species), alpha = 0.4, color = NA)+
  geom_point(aes(x = Culture2, y = value, fill = Species), size = 3, color = "black", pch = 21,
             position = position_jitter(width = 0.05, seed = 12))+
  facet_grid(variable2 ~ Species, scales = "free_y", labeller = label_parsed) +
  xlab("")+ 
  ylab("")+
  scale_colour_discrete(labels = function(z) scales::label_parse()(sub("bold","",z)))+
  scale_fill_discrete(labels = function(z) scales::label_parse()(sub("bold","",z)))+
  theme_classic()+
  theme(strip.background = element_rect(colour = "black", fill = "grey85", size = 0.1),
        panel.border=element_rect(colour="black",size = 0.1, fill = NA),
        panel.spacing = unit(0.3, "lines"),
        axis.text.y = element_text(size = 12, colour = "black"),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        legend.position = "bottom",
        legend.text=element_text(size=12),
        legend.title=element_text(size=12,face="bold"),
        strip.text.x=element_text(size=12),
        strip.text.y=element_text(size=12))

sample plot with strip labels and facet text fixed


Sample data:

set.seed(42)
n <- 420
group.data <- data.frame(Culture2 = sample(c("Auri", "Grav"), size=n, replace=TRUE), value=runif(n), Species=sample(c("Bos", "Cerv", "Equus"), size=n, replace=TRUE), variable=sample(c("d13C", "d15N", "d34S"), size=n, replace=TRUE))
head(group.data)
#   Culture2      value Species variable
# 1     Auri 0.11483254   Equus     d15N
# 2     Auri 0.48275690   Equus     d13C
# 3     Auri 0.97917358   Equus     d34S
# 4     Auri 0.81151679     Bos     d13C
# 5     Grav 0.54291282   Equus     d34S
# 6     Grav 0.07236709    Cerv     d34S