rggplot2bar-chart

ggplot: same bar widths with different number of bars


I would like to have barplots in which the bars have the same width across different plots, no matter how many bars are shown. I do not want to show the plots on the same page, or arrange them with facets, grid.arrange or anything like that, but just have two plots with bars of the same width.

I could do this by just multiplying the width by the number of bars in the plot divided by the number of bars in the plot with the most bars (see example). But it would be more convenient and somewhat cleaner code if I could do this without any computations before the ggplot call.

Is there a way to specify the bar widths in a unit like lines, em, centimeters?

Or can I access the number of levels of the variable mapped to the x-aesthetic in the call to geom_col? (Note the variable mapped to the x-aesthetic changes between plots)

Or is there another simple solution?

ggplot(data.frame(x=factor(1:2), y=4:5), aes(x=x, y=y)) + 
  geom_col(width=0.7*2/3)

ggplot(data.frame(A=factor(1:3), y=3:5), aes(x=A, y=y)) + 
  geom_col(width=0.7*3/3)

Solution

  • AFAIK, you can not set an absolute width to geom_col()/geom_bar(), so you'd either have to precalculate the proportions and aspect ratio of the bars or use geom_segment() that takes a size argument that is absolute. These aren't internally parameterised as rectangles and don't take seperate colour and fill arguments though.

    library(ggplot2)
    library(patchwork)
    
    g1 <- ggplot(data.frame(x=factor(1:2), y=4:5), aes(x=x, y=y, xend = x, yend = 0)) + 
      geom_segment(size = 20)
    
    g2 <- ggplot(data.frame(A=factor(1:3), y=3:5), aes(x=A, y=y, xend=A, yend = 0)) + 
      geom_segment(size = 20)
    
    g1 + g2