rggplot2plotlabel

How to fix xlabels with multiple categories in R ggplot?


I am trying to generate a Bar plot with multiple categories using ggplot. I am having a hard time fixing the labels. I was trying to use the solution I found here: ggplot2 multiple sub groups of a bar chart

But still the labels are not correct. The solution from the link above generates this graph:

enter image description here

However, when I save the graph into a jpeg the xlabels disappear. Does anyone knows what could be happening? It seems that I am suppressing the xlabels and puttings stuff on top with these codes. Does anyone has a different solution then the one from the link?

enter image description here

This is the code I am using:

dodge <- position_dodge(width = 0.9)
g1 <- ggplot(data = df, aes(x = interaction(gender, nexp), y = perc, fill = factor(positive))) +
  geom_bar(stat = "identity", position = position_dodge())  +
  coord_cartesian(ylim = c(0, 65)) +
  annotate("text", x = c(1.5, 3.5, 5.5, 7.5, 9.5), y = -10,
           label = rep(c("0", "1", "2", "3", "4"), 1)) +
  annotate("text", x= c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), y = - 15, 
           label = rep(c("Man", "Woman","Man", "Woman","Man", "Woman","Man", "Woman","Man", "Woman"))) +
  theme_classic() +
  theme(plot.margin = unit(c(1, 1, 4, 1), "lines"),
        axis.title.x = element_blank(),
        axis.text.x = element_blank()) +
  geom_text(aes(label=count), 
                position = position_dodge(width = 1), 
                vjust=-.5, size = 4) +
  labs(title = "Percentage of positive and negative outcomes by number of experiencial activity and gender") +
         theme(plot.title = element_text(hjust = .1),
               plot.title.position = "plot") +
  guides(fill = guide_legend(title.position="top", title ="Outcome") ) + 
  scale_fill_brewer(palette = "Set1", labels = c("Negative", "Positive")) +
  ylab("Percentage per number of experiences (%)")

g1

g2 <- ggplot_gtable(ggplot_build(g1))
g2$layout$clip[g2$layout$name == "panel"] <- "off"
grid.draw(g2)
ggsave("plot.jpeg", dpi = "retina")

And this is the data:

df <- structure(list(nexp = c(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 
                             3, 3, 3, 4, 4, 4, 4), gender = structure(c(1L, 1L, 2L, 2L, 1L, 
                                                                        1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), levels = c("Man", 
                                                                                                                                                "Woman"), class = "factor"), positive = c(0, 1, 0, 1, 0, 1, 0, 
                                                                                                                                                                                          1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1), count = c(30L, 47L, 15L, 
                                                                                                                                                                                                                                            43L, 56L, 94L, 69L, 121L, 40L, 80L, 74L, 170L, 19L, 53L, 50L, 
                                                                                                                                                                                                                                            134L, 2L, 7L, 14L, 36L), total = c(135L, 135L, 135L, 135L, 340L, 
                                                                                                                                                                                                                                                                               340L, 340L, 340L, 364L, 364L, 364L, 364L, 256L, 256L, 256L, 256L, 
                                                                                                                                                                                                                                                                               59L, 59L, 59L, 59L), perc = c(22.2222222222222, 34.8148148148148, 
                                                                                                                                                                                                                                                                                                             11.1111111111111, 31.8518518518519, 16.4705882352941, 27.6470588235294, 
                                                                                                                                                                                                                                                                                                             20.2941176470588, 35.5882352941176, 10.989010989011, 21.978021978022, 
                                                                                                                                                                                                                                                                                                             20.3296703296703, 46.7032967032967, 7.421875, 20.703125, 19.53125, 
                                                                                                                                                                                                                                                                                                             52.34375, 3.38983050847458, 11.864406779661, 23.728813559322, 
                                                                                                                                                                                                                                                                                                             61.0169491525424)), row.names = c(NA, -20L), class = "data.frame")

Solution

  • Here is one potential fix...

    I put the experimental replicates toward the top of the plot and added some shading to differentiate them. I don't think it ever really makes sense to have a giant space at the bottom of the graph or two axis label. I avoid those things with facets and other tricks like annotate_text which you use nicely here. I just figured to move them toward the top. the shading helps differentiate the exp replicates.

        df <- structure(list(nexp = c(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3,
    3, 3, 3, 4, 4, 4, 4), gender = structure(c(1L, 1L, 2L, 2L, 1L,
    1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), levels = c("Man",
    "Woman"), class = "factor"), positive = c(0, 1, 0, 1, 0, 1, 0,
    1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1), count = c(30L, 47L, 15L,
    43L, 56L, 94L, 69L, 121L, 40L, 80L, 74L, 170L, 19L, 53L, 50L,
    134L, 2L, 7L, 14L, 36L), total = c(135L, 135L, 135L, 135L, 340L,
    340L, 340L, 340L, 364L, 364L, 364L, 364L, 256L, 256L, 256L, 256L,
    59L, 59L, 59L, 59L), perc = c(22.2222222222222, 34.8148148148148,
    11.1111111111111, 31.8518518518519, 16.4705882352941, 27.6470588235294,
    20.2941176470588, 35.5882352941176, 10.989010989011, 21.978021978022,
    20.3296703296703, 46.7032967032967, 7.421875, 20.703125, 19.53125,
    52.34375, 3.38983050847458, 11.864406779661, 23.728813559322,
    61.0169491525424)), row.names = c(NA, -20L), class = "data.frame")
    
    
    library(ggplot2) ## libraries
    
    
    
    ## start plotting
    dodge <- position_dodge(width = 0.9)
    g1 <- ggplot(data = df, aes(x = interaction(gender, nexp), y = perc, fill = factor(positive))) +
      ### add rectangles for shading background 
      annotate('rect', xmin = seq(0.5,8.5, by = 4), xmax = seq(2.5,10.5, by = 4), ymin = rep(0, 3), ymax = rep(80, 3), fill = "#b9b0b033") +                        geom_bar(stat = "identity", position = position_dodge())  +                     
      annotate("text", x = c(1.5, 3.5, 5.5, 7.5, 9.5), y = 75,
               label = rep(c("0", "1", "2", "3", "4"), 1)) +   ## put exp number 1-4 above bars 
      coord_cartesian(ylim = c(0, 80)) +
      theme_classic() +
      #theme(plot.margin = unit(c(1, 1, 4, 1), "lines")) +    # unnecessary
      geom_text(aes(label=count), 
                position = position_dodge(width = 1), 
                vjust=-.5, size = 4) +
      labs(title = "Percentage of positive and negative outcomes by number of experiencial activity and gender") +
      theme(plot.title = element_text(hjust = .1),
            plot.title.position = "plot", 
            axis.text.x= element_text(angle = 45, hjust = 1)) +
      guides(fill = guide_legend(title.position="top", title ="Outcome") ) + 
      scale_fill_brewer(palette = "Set1", labels = c("Negative", "Positive")) + 
      scale_x_discrete(labels = rep(c("man", "woman"), 5)) +
      ylab("Percentage per number of experiences (%)") + xlab("gender")
    
    # g1
    
    ## Saving plot
    g2 <- ggplot_gtable(ggplot_build(g1))
    g2$layout$clip[g2$layout$name == "panel"] <- "off"
    grid::grid.draw(g2)
    ggsave("plot.jpeg", dpi = 300, width = 22, height = 10, units = "cm")
    

    CLICK TO SEE New Fig: plot.jpeg