Expression in ggplot2 facet labels
Asked Answered
A

4

11

I would like to have an R expression in a ggplot2 facet label.

Let's say I'm plotting the tips data.frame:

library(reshape2)
> head(tips)
  total_bill  tip    sex smoker day   time size
1      16.99 1.01 Female     No Sun Dinner    2
2      10.34 1.66   Male     No Sun Dinner    3
3      21.01 3.50   Male     No Sun Dinner    3
4      23.68 3.31   Male     No Sun Dinner    2
5      24.59 3.61 Female     No Sun Dinner    4
6      25.29 4.71   Male     No Sun Dinner    4

as follows:

library(ggplot2)
sp <- ggplot(tips, aes(x=total_bill, y=tip/total_bill)) + 
         geom_point(shape=1) + 
         facet_wrap(~sex, ncol = 1)

enter image description here

Instead of having "Female" and "Male" as facet labels I would like to have: "Female subjects" and "Male subjects", respectively. As far as I know italicizing a label in R is achieved through the expression function, but I don't know how to combine that with facet_wrap.

Asmara answered 19/9, 2015 at 17:52 Comment(4)
You could use a custom function, you can use with the labeller argument, see hereDisremember
It's not clear to me how you get the labeller argument of facet_grid to replace the factor with an expression and have the facets in rows with the labels on top, as in my example (rather than on the side as in facet_grid labels for rows).Asmara
Did you check this topic ? It might help #20038343Oared
It's close but my labels are compound - an italicized word followed by an non-italicized one. I don't see how I can achieve that with element_text of themeAsmara
J
7

Looks overly complicated, but works. You'll have to use facet_grid though.

make_label <- function(value) {
  x <- as.character(value)
  bquote(italic(.(x))~subjects)
}

plot_labeller <- function(variable, value) {
  do.call(expression, lapply(levels(value), make_label))
}

ggplot(tips, aes(x=total_bill, y=tip/total_bill)) + 
  geom_point(shape=1) + 
  facet_grid(.~sex, labeller = plot_labeller)

enter image description here

Jelks answered 21/9, 2015 at 11:5 Comment(2)
I knew it had to be a function but could't get it working. Any thoughts on why this doesn't work with facet_wrap?Disremember
@Disremember facet_wrap does not support custom labellers as is (I don't know why), but there is a low-level workaround as shown here.Jelks
U
10

As of ggplot2 2.1.0:

data(tips, package="reshape2")
library(ggplot2)
ggplot(tips, aes(x=total_bill, y=tip/total_bill)) + 
  geom_point(shape=1) + 
  facet_wrap(~sex, ncol=1, 
             labeller=label_bquote(.(levels(tips$sex)[sex])~subjects))
Uvula answered 22/3, 2017 at 11:48 Comment(1)
Fails with the error Error in levels(tips$sex)[sex] : could not find function "[" somehow the bquote seems to be evaluated in an empty environment? Not sure if this is a bug or a feature of a new ggplot2 version.Moffit
J
7

Looks overly complicated, but works. You'll have to use facet_grid though.

make_label <- function(value) {
  x <- as.character(value)
  bquote(italic(.(x))~subjects)
}

plot_labeller <- function(variable, value) {
  do.call(expression, lapply(levels(value), make_label))
}

ggplot(tips, aes(x=total_bill, y=tip/total_bill)) + 
  geom_point(shape=1) + 
  facet_grid(.~sex, labeller = plot_labeller)

enter image description here

Jelks answered 21/9, 2015 at 11:5 Comment(2)
I knew it had to be a function but could't get it working. Any thoughts on why this doesn't work with facet_wrap?Disremember
@Disremember facet_wrap does not support custom labellers as is (I don't know why), but there is a low-level workaround as shown here.Jelks
M
3

The following works for R 4.0.3 and ggplot2 3.3.2

library(ggplot2)
data(tips, package="reshape2")
tips$sex = as.character(tips$sex)
sp <- ggplot(tips, aes(x=total_bill, y=tip/total_bill)) + 
  geom_point(shape=1) + 
  facet_wrap(~sex, ncol = 1, labeller = label_bquote(italic(.(sex))~subjects))
sp

It uses label_bquote as suggested by @Stéphane Laurent but does not require converting levels into the correct character within the bquote which failed for me.

Moffit answered 23/10, 2020 at 19:12 Comment(0)
P
2

I know this is an old post, but I like the label_parsed function. It works with labels in a factor:

data(tips, package="reshape2")
library(ggplot2)
tips %>%
  mutate(sex = factor(sex,
                      levels = c("Female", "Male"),
                      labels = c(expression(italic(Female)~Subjects), 
                                 expression(italic(Male)~Subjects)))) %>%
  ggplot(aes(x=total_bill, y=tip/total_bill)) + 
  geom_point(shape=1) + 
  facet_wrap(~sex, ncol = 1,labeller = label_parsed)

This returns

Link to output

Pellagra answered 4/5, 2023 at 16:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.