Search code examples
rlabelpanelfacet-wrap

How can I change the order and label of a panel in facet_wrap?


Folks-

I'm embarrassed to solicit advice for something that seems like it should be so easy, but my frustration outweighs my embarrassment. How can I change the order, label, and line color of a single panel in facet_wrap while using automatic ordering, labelling, and coloring for the other panels. Specifically, I would like to plot the "Bronx Cheer Rate" for the country Freedonia and each of its four states (Chico, Groucho, Harpo, and Zeppo, named for Freedonia's founding fathers), but making "Freedonia" the first panel in the graph and making its line black. This is what I have:

enter image description here

My (admittedly inelegant) solution is to

  1. Recode "Freedonia" as "aaa" (so it appears first).
  2. Use a geom_line statement that subsets the data to "aaa" and changes the line color to black.
  3. Change the label of the panel back to "Freedonia." I'm fine until I get to the third step.

Here's some code with a reproducible (or is it replicable?) example:

library(dplyr)
library(ggplot2)
library(data.table)

#Simulate Data
set.seed(581)
state <- rep(c("Chico","Groucho","Harpo","Freedonia","Zeppo"), each=4)
x <- rep(1:4, times = 5)
y <- 100 + rnorm(20, 0, 5)*x + rnorm(20, 0, 20)
df <- cbind(state, x, y) %>% data.table() %>% 
  .[ , .(state, x = as.numeric(x), y = as.numeric(y))]

#Recode 
df <- df[ , state := recode(state, "Freedonia" = "aaa")]

#Generate Labels
labels <- unique(df$state[which(state != "Freedonia")])
labels <- c("Freedonia", labels)

#Grid Plot with Freedonia First
p <- ggplot(df, aes(x, y, color = state)) + 
  geom_line() +
  geom_line(data = subset(df, state == "aaa"), color = "black") + 
  ggtitle("Average Bronx Cheers by Quarter (1934)") + 
  theme_bw() +
  theme(legend.position = "none") + 
  theme(plot.title = element_text(hjust = 0.5)) + 
  xlab("Quarter") +
  ylab("Bronx Cheer Rate") +
  #facet_wrap(~ state)
  #facet_wrap(~ state, labeller = labeller(state = labels)) 
  facet_wrap(~ state, labeller = labeller(setNames(nm = labels)))
p

Here's the result.

enter image description here

I realize that with just five panels, it would be trivial to do this manually (with, say, scale_fill_manual), but you may have surmised that I'm not really interested in Freedonia, but, rather, in a state that has many counties--too many to do manually. I've looked not exhaustively, but thoroughly, and haven't seen anything that addresses this exact problem.

I'd be very grateful for your help.

Regards, David


Solution

  • You could set up the factor levels of state in a way that 'Freedonia' is the first level and rest of them come later.

    library(ggplot2)
    
    df$state <- factor(df$state, levels = c('Freedonia', 
                       setdiff(unique(df$state), 'Freedonia')))
    
    ggplot(df, aes(x, y, color = state)) + 
      geom_line() +
      geom_line(data = subset(df, state == "Freedonia"), color = "black") + 
      ggtitle("Average Bronx Cheers by Quarter (1934)") + 
      theme_bw() +
      theme(legend.position = "none") + 
      theme(plot.title = element_text(hjust = 0.5)) + 
      xlab("Quarter") +
      ylab("Bronx Cheer Rate") +
      facet_wrap(~ state)
    

    enter image description here