8

I'm trying to change labels for ggplot graph with facets, and am using a variable from the dataframe which is not faceted. The code is as belows-

iris %>%
  group_by(Species) %>%
  summarise(lbl = mean(Petal.Length)) %>%
  select(lbl) %>%
  unlist() -> lbls
lbls <- map2(unique(iris$Species), lbls, paste, sep = "\n")
iris %>%
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, group = 1)) +
  geom_point() +
  facet_wrap(~ Species, labeller = lbls)

However, this gives me the following error-

Error in cbind(labels = list(), list(`{`, if (!is.null(.rows) || 
!is.null(.cols)) { : 
 number of rows of matrices must match (see arg 2)

I've looked at the labeller function and different options but most of them seem to be for variables which are included in facets. Is there a way this can be done? Any leads appreciated, thanks!

Mridul Garg
  • 477
  • 1
  • 8
  • 17

2 Answers2

7

From the documentation on ?labeller, labeller can also be a named character vector. Note that we need to wrap the character vector in the labeller function. Also from looking at the examples in the help file, we need to pass the facetting variable Species as the argument to labeller. Thus the call should look something like:

labeller = labeller(Species = setNames(unlist(lbls), unique(iris$Species)))

The code should then be:

iris %>%
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, group = 1)) +
  geom_point() +
  facet_wrap(~ Species, labeller = labeller(Species = setNames(unlist(lbls), unique(iris$Species))))

Also, a much cleaner way to create the labels would be without map2:

lbls <- setNames(paste(unique(iris$Species), lbls, sep = "\n"), unique(iris$Species))

enter image description here

Mike H.
  • 13,960
  • 2
  • 29
  • 39
  • Thanks, this works great! I missed the wrap part as well as passing the faceting variable. I think I should spend more time reading the docs for this – Mridul Garg Mar 26 '18 at 18:26
  • @MridulGarg the labeller functions and docs can certainly be confusing. Especially if you decide to use your own function rather than a named vector – Mike H. Mar 26 '18 at 18:27
6

You could create a new facetting column on the fly and avoid labeller pain:

iris %>%
  group_by(Species) %>% 
  mutate(label = paste0(Species, "\n", round(mean(Petal.Length),2))) %>% 
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, group = 1)) +
    geom_point() +
    facet_wrap(~ label)

enter image description here

eipi10
  • 91,525
  • 24
  • 209
  • 285
  • Thanks for this but I'm already creating a new column for faceting so this won't work out for me. The iris example was just to reproduce the issue I was facing, but I appreciate your reply! – Mridul Garg Mar 26 '18 at 18:14
  • You can still use this method. Just create a label column by pasting your new facet column to the mean of whatever column your using for the mean. – eipi10 Mar 26 '18 at 18:21