Moving the strip labels on a facet wrapped graph to the interior of each graph

Viewed 1394

Here is the reproducible code:

mpg %>%
    ggplot(aes(x = year, y = cty)) +
    geom_line() +
    geom_point() +
    facet_wrap(~manufacturer) +
    theme_bw() +
    theme(panel.grid.major = element_blank(),
          panel.grid.minor = element_blank(),
          strip.background = element_blank(),
          panel.border = element_rect(color = "black"),
          strip.text.x = element_text(vjust = -3))

Reproducible Graph - Not what I wanted I wanted to move the manufacturer names into the interior of the graph (inside the black border for each graph), but when I alter the vjust argument, the manufacturer names are obscured BEHIND the graph. How do I make fix this?

2 Answers

You could use annotate to add a title to each graph and hide the actual facet title to achieve this effect.

mpg %>%
  ggplot(aes(x = year, y = cty)) +
  geom_line() +
  geom_point() +
  annotate("text", x= 2004, y = 30, label =unique(mpg$manufacturer))+
  facet_wrap(~manufacturer) +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        strip.background = element_blank(),
        panel.border = element_rect(color = "black"),
        strip.text.x = element_blank()) 

result

I might be wrong but I don't think facet_wrap supports that feature.

I couldn't figure out a good way with setting blank theme elements, but I can offer this hack: if the labels are essentially the distinct combination of 1) the faceting variable (in this case, manufacturer), 2) the midpoint of x-axis values, and 3) the maximum of y-axis values, you can create a data frame of labels. You could do this inline as the data argument to geom_text, but it's cleaner to show in a separate data frame.

library(tidyverse)

mpg_labels <- mpg %>%
  mutate(year = mean(c(min(year), max(year))), cty = max(cty)) %>%
  distinct(manufacturer, year, cty)

head(mpg_labels)
#> # A tibble: 6 x 3
#>   manufacturer  year   cty
#>   <chr>        <dbl> <dbl>
#> 1 audi         2004.    35
#> 2 chevrolet    2004.    35
#> 3 dodge        2004.    35
#> 4 ford         2004.    35
#> 5 honda        2004.    35
#> 6 hyundai      2004.    35

Then make the default strips and their backgrounds blank, and the space normally reserved for strips will be dropped (I would have guessed having a blank space in place of strips, so this is nicer than I thought it would be).

annotate works instead of geom_text if you know in advance exactly where you want the labels and won't need to scale, but I almost always opt for geom_text for scaleability and to keep from hard-coding anything.

mpg %>%
  ggplot(aes(x = year, y = cty)) +
  geom_line() +
  geom_point() +
  geom_text(aes(label = manufacturer), data = mpg_labels, vjust = 1) +
  facet_wrap(~manufacturer) +
  theme_bw() +
  theme(panel.grid = element_blank(),
        strip.text.x = element_blank(),
        strip.background = element_blank())

Created on 2018-11-06 by the reprex package (v0.2.1)

Related