Reputation: 169
I need to create a multi-panel figure where the tick labels for the y-axis (factor) are italicized for some panels and plain text for other panels.
Here is a reproducible example, using made up data, of one thing I've tried:
library(ggplot2)
## Example data
df <- data.frame(var = c("Grass cover", "River depth", "Canis familiaris", "Canis lupus", "Canis latrans"),
coef = c(0.6, 0.4, 0.8, 0.1, 0.5),
se = c(0.3, 0.4, 0.4, 0.05, 0.2),
panel = c(rep("Environment", 2), rep("Canid abundance", 3)))
## multi-panel plot
ggplot(df, aes(y = var, x = coef, xmin = coef - se, xmax = coef + se)) +
geom_pointrange() +
facet_wrap(~ panel, scales = "free_y", ncol = 1) +
labs(y = NULL) +
theme(axis.text.y = element_text(face = c(rep("plain", 2), rep("italic", 3))))
Notice that only "Canis lupus" is italicized in the top panel. The desired figure would have all scientific names (y-axis labels) in the first panel be italics but labels in the bottom panel should be plain. In the real data, I have 4 panels, 2 of which need italics.
It appears that a vectorized face
argument in element_text()
is recycled between panels. I've also tried axis.text.y = element_text(face = rep("italic", 3), c(rep("plain", 2)))
which results in all 5 y-axis labels being italicized.
If possible, I'd prefer not to use multiple ggplot objects (i.e., grid_arrange()
or cowplot()
). Though, I'm open to any solution that allows me to tweak all visual formatting elements.
I think there must be a solution using expression()
, but I haven't been able to work it out.
Upvotes: 3
Views: 616
Reputation: 124048
One option to achieve your desired result would be to make use of the ggtext
package which allows for using markdown syntax and/or HTML/CSS to style labels and theme elements.
theme(axis.text.y = ggtext::element_markdown())
the y axis labels will be parsed as markdown code.* ... *
.library(ggplot2)
library(ggtext)
df <- data.frame(var = c("Grass cover", "River depth", "Canis familiaris", "Canis lupus", "Canis latrans"),
coef = c(0.6, 0.4, 0.8, 0.1, 0.5),
se = c(0.3, 0.4, 0.4, 0.05, 0.2),
panel = c(rep("Environment", 2), rep("Canid abundance", 3)))
df$var <- ifelse(df$panel %in% "Canid abundance", paste0("*", df$var, "*"), df$var)
## multi-panel plot
ggplot(df, aes(y = var, x = coef, xmin = coef - se, xmax = coef + se)) +
geom_pointrange() +
facet_wrap(~ panel, scales = "free_y", ncol = 1) +
labs(y = NULL) +
theme(axis.text.y = ggtext::element_markdown())
Upvotes: 2
Reputation: 8110
Here is another option.
library(tidyverse)
df <- tibble(var = c("Grass cover", "River depth", "Canis familiaris", "Canis lupus", "Canis latrans"),
coef = c(0.6, 0.4, 0.8, 0.1, 0.5),
se = c(0.3, 0.4, 0.4, 0.05, 0.2),
panel = c(rep("Environment", 2), rep("Canid abundance", 3)))
df %>%
mutate(lab = map2_chr(var, panel,
~ifelse(.y == "Canid abundance",
paste0('italic("', .x,'")'),
paste0('"', .x,'"')))) %>%
ggplot(aes(y = lab, x = coef, xmin = coef - se, xmax = coef + se)) +
geom_pointrange() +
facet_wrap(~ panel, scales = "free_y", ncol = 1) +
labs(y = NULL) +
scale_y_discrete(label = function(x) parse(text = x))
Upvotes: 4