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.

Nancy
  • 3,989
  • 5
  • 31
  • 49
user1701545
  • 5,706
  • 14
  • 49
  • 80
  • You could use a custom function, you can use with the labeller argument, see [here](http://stackoverflow.com/questions/30923852/include-t-character-in-facet-strip-text-with-custom-labeller) – RHA Sep 19 '15 at 20:22
  • 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). – user1701545 Sep 19 '15 at 21:04
  • Did you check this topic ? It might help http://stackoverflow.com/questions/20037843/how-to-use-italics-for-facet-labels-in-ggplot2 – Boidot Sep 19 '15 at 21:07
  • 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 theme – user1701545 Sep 19 '15 at 21:16

4 Answers4

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))
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
  • 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. – jakob-r Oct 23 '20 at 19:13
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

tonytonov
  • 25,060
  • 16
  • 82
  • 98
  • 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? – RHA Sep 22 '15 at 06:31
  • @RHA `facet_wrap` does not support custom labellers as is (I don't know why), but there is a low-level workaround as shown [here](http://stackoverflow.com/questions/19282897/how-to-add-expressions-to-labels-in-facet-wrap). – tonytonov Sep 22 '15 at 06:47
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.

jakob-r
  • 6,824
  • 3
  • 29
  • 47
1

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

Martin Gal
  • 16,640
  • 5
  • 21
  • 39
Joe Robert
  • 84
  • 3