Search code examples
rggplot2geom-barfacet-grid

Removing unused factors from grouped facet_grid bar plot


I have read through the first page of results for this search but nothing seems to be working.

I need to create a plot that drops the unused levels on X, so that Strongly disagree, Disagree, and Mildyl disagree are grouped into the facet of 'detractors', then Uncertain and Mildly agree are grouped into the facet of 'Passive', and Agree and Strongly agree are grouped into 'Promoters'.

Here is a dput of the data

structure(list(area = c("NPS.recomm", "invest", "commit", "involve", 
"all.consid", "exit.in", "FBM.recomm", "NPS.recomm", "invest", 
"commit", "involve", "all.consid", "exit.in", "FBM.recomm", "NPS.recomm", 
"invest", "commit", "involve", "all.consid", "exit.in", "FBM.recomm"
), response.cat = c("Strongly \ndisagree", "Disagree", "Mildly \ndisagree", 
"Uncertain", "Mildly \nagree", "Agree", "Strongly \nagree", "Strongly \ndisagree", 
"Disagree", "Mildly \ndisagree", "Uncertain", "Mildly \nagree", 
"Agree", "Strongly \nagree", "Strongly \ndisagree", "Disagree", 
"Mildly \ndisagree", "Uncertain", "Mildly \nagree", "Agree", 
"Strongly \nagree"), response.set = c("Detractors", "Detractors", 
"Detractors", "Passive", "Passive", "Promoters", "Promoters", 
"Detractors", "Detractors", "Detractors", "Passive", "Passive", 
"Promoters", "Promoters", "Detractors", "Detractors", "Detractors", 
"Passive", "Passive", "Promoters", "Promoters"), split = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L), .Label = c("curr.score", "prior.score", "bench.score"
), class = "factor"), score = c(7, 6, 3, 15, 16, 39, 14, 5, 4, 
4, 15, 22, 33, 18, 14, 10, 6, 16, 15, 29, 10)), row.names = c(NA, 
-21L), .Names = c("area", "response.cat", "response.set", "split", 
"score"), class = "data.frame")

And here is the current code

col.set <- c("dodgerblue4", "#FF9933", "gold")
plot.labels <- c("group1","group2","group3")
curr.plot <- ggplot(plot.data, aes(response.cat, score)) +   
  facet_grid(. ~ response.set, scales="free_x", space = "free_x") +
  geom_bar(aes(fill = split), position = "dodge", stat="identity")+
  scale_fill_manual(values=c(col.set), labels= plot.labels )+
  ylim(c(0,100))+
  theme(legend.title = element_blank(), legend.position = "bottom", 
        legend.text=element_text(colour= "gray23"), legend.key.height=unit(3,"mm")) +
  theme(axis.title= element_blank()) +
  scale_x_discrete(limits = c("Strongly \ndisagree","Disagree","Mildly \ndisagree","Uncertain","Mildly \nagree","Agree","Strongly \nagree"))+
  geom_text(aes(fill = split, label = paste0(score,"%")), colour = "gray23", vjust=-1, position=position_dodge(.9),size=3)+  
  theme(panel.grid.minor.y = element_blank()) +
  theme(panel.grid.major.y = element_line(colour = "gray")) +
  theme(panel.grid.major.x =element_blank(), panel.grid.minor.x =element_blank()) +
  theme(panel.background = element_rect(fill="white")) +
  theme(axis.text.x = element_text(colour = "gray23")) +
  theme(axis.text.y = element_text(colour = "gray23")) +
  theme(axis.ticks.y=element_blank()) 

Which produces the below, you can see the detractors facet looks right, but the other two facets contain unused factors. I just want the X labels appearing once across the bottom.Also weird how it has spaced the facets given the number of categories in each.

Any ideas?

enter image description here


Solution

  • The problem is your use of scale_x_discrete. You can transform response.cat into an ordered factor instead:

    plot.data$response.cat <- factor(plot.data$response.cat, levels = c("Strongly \ndisagree","Disagree","Mildly \ndisagree","Uncertain","Mildly \nagree","Agree","Strongly \nagree"))
    
    ggplot(plot.data, aes(response.cat, score)) +   
      facet_grid(. ~ response.set, scales="free_x", space = "free_x") +
      geom_bar(aes(fill = split), position = "dodge", stat="identity")+
      scale_fill_manual(values=c(col.set), labels= plot.labels )+
      ylim(c(0,100))+
      theme(legend.title = element_blank(), legend.position = "bottom", 
            legend.text=element_text(colour= "gray23"), legend.key.height=unit(3,"mm")) +
      theme(axis.title= element_blank()) +
      geom_text(aes(fill = split, label = paste0(score,"%")), colour = "gray23", vjust=-1, position=position_dodge(.9),size=3)+  
      theme(panel.grid.minor.y = element_blank()) +
      theme(panel.grid.major.y = element_line(colour = "gray")) +
      theme(panel.grid.major.x =element_blank(), panel.grid.minor.x =element_blank()) +
      theme(panel.background = element_rect(fill="white")) +
      theme(axis.text.x = element_text(colour = "gray23")) +
      theme(axis.text.y = element_text(colour = "gray23")) +
      theme(axis.ticks.y=element_blank()) 
    

    enter image description here