Search code examples
rggplot2bar-chartgeom-bar

Constant width in ggplot barplots


How to make the width of bars and spaces between them fixed for several barplots using ggplot, having different number of bars on each plot?

Here is a failed try:

m <- data.frame(x=1:10,y=runif(10))
ggplot(m, aes(x,y)) + geom_bar(stat="identity")

enter image description here

ggplot(m[1:3,], aes(x,y)) + geom_bar(stat="identity")

enter image description here

Adding width=1 to geom_bar(...) doesn't help as well. I need the second plot automatically to have less width and the same bar width and spaces as the first one.


Solution

  • Edit:

    It appears the OP simply wants this:

    library(gridExtra)
    grid.arrange(p1,arrangeGrob(p2,widths=c(1,2),ncol=2), ncol=1)
    

    I am not sure, if it's possible to pass absolute widths to geom_bar. So, here is an ugly hack:

    set.seed(42)
    m <- data.frame(x=1:10,y=runif(10))
    p1 <- ggplot(m, aes(x,y)) + geom_bar(stat="identity")
    p2 <- ggplot(m[1:3,], aes(x,y)) + geom_bar(stat="identity")
    g1 <- ggplotGrob(p1)
    g2 <- ggplotGrob(p2)
    

    I used str to find the correct grob and child. You could use more sophisticated methods to generalize this if necessary.

    #store the old widths
    old.unit <- g2$grobs[[4]]$children[[2]]$width[[1]]
    
    #change the widths
    g2$grobs[[4]]$children[[2]]$width <- rep(g1$grobs[[4]]$children[[2]]$width[[1]],
                                             length(g2$grobs[[4]]$children[[2]]$width))
    
    #copy the attributes (units)
    attributes(g2$grobs[[4]]$children[[2]]$width) <- attributes(g1$grobs[[4]]$children[[2]]$width)
    
    #position adjustment (why are the bars justified left???)
    d <- (old.unit-g2$grobs[[4]]$children[[2]]$width[[1]])/2
    attributes(d) <- attributes(g2$grobs[[4]]$children[[2]]$x)
    g2$grobs[[4]]$children[[2]]$x <- g2$grobs[[4]]$children[[2]]$x+d
    
    #plot
    grid.arrange(g1,g2)
    

    enter image description here