rplotggplot2facetaxis-labels

Wrong axis labels for ggplot facet grid


I was answering this question that I faced a strange problem;

I want to make a bar plot with ggplot2 and have x axis labels as the last character of Group column. Use substring(Group, 3, 3) for this purpose:

substring(df$Group, 3, 3)
# [1] "1" "2" "3" "1" "2" "1" "2" "3" "4"

But when I use it in ggplot like below, it prints 1 instead of 4 at the last tick;

ggplot(data=df, aes(x=Group, y=Value)) +
  geom_bar(stat="identity") + 
  scale_x_discrete(labels = substring(Group, 3, 3), expand=c(0.1,0.1)) +
  facet_grid(~ substring(df$Group, 1, 1), space="free_x", scales="free_x", switch="x") + 
  theme_bw() +
  theme(strip.placement = "outside",
        strip.background = element_rect(fill=NA,colour="grey50"),
        panel.spacing=unit(0,"cm"))

barplot

I can get it to work by using labels =unique(substring(Group, 3, 3) but would someone explain what's going on?

Data:

  df <- structure(list(Group = structure(1:9, .Label = c("1_1", "1_2",  
  "1_3", "2_1", "2_2", "3_1", "3_2", "3_3", "3_4"), class = "factor"),  
      Value = c(-1.23, 2.34, 0.56, 1.87, -2.4, 5.54, -0.98, -2.31,  
      6)), .Names = c("Group", "Value"), row.names = c(NA, -9L), class = "data.frame")

# > df

#   Group Value 
# 1   1_1 -1.23 
# 2   1_2  2.34 
# 3   1_3  0.56 
# 4   2_1  1.87 
# 5   2_2 -2.40 
# 6   3_1  5.54 
# 7   3_2 -0.98 
# 8   3_3 -2.31 
# 9   3_4  6.00

Solution

  • I think that @Gregor's answer is the way to go, but I can explain the error. Even if you add df$ before group, you get the behavior you described. You can see why if you don't let the scales vary:

    ggplot(data=df, aes(x=Group, y=Value)) +
      geom_bar(stat="identity") + 
      scale_x_discrete(labels = substring(df$Group, 3, 3), expand=c(0.1,0.1)) +
      facet_grid(~ substring(Group, 1, 1), switch="x") + 
      theme_bw() +
      theme(strip.placement = "outside",
            strip.background = element_rect(fill=NA,colour="grey50"),
            panel.spacing=unit(0,"cm"))
    

    gives: enter image description here

    As you can see, here it gives the "4" correctly. However, when you are setting the labels directly, it is setting them (in order) for each facet separately when you allow the scales to vary. In essence, you are setting the labels to "1, 2, 3, 1, 2, 1, 2, 3, 4" each time, but only using the first few.

    If you want to stick closer to your current, you'll also need to set the breaks, e.g.:

    ggplot(data=df, aes(x=Group, y=Value)) +
      geom_bar(stat="identity") + 
      scale_x_discrete(breaks = df$Group, labels = substring(df$Group, 3, 3), expand=c(0.1,0.1)) +
      facet_grid(~ substring(Group, 1, 1), space="free_x", scales="free_x", switch="x") + 
      theme_bw() +
      theme(strip.placement = "outside",
            strip.background = element_rect(fill=NA,colour="grey50"),
            panel.spacing=unit(0,"cm"))
    

    Which gives

    enter image description here