Automatically resize bars in ggplot for uniformity

2019-07-13 13:30发布

问题:

I generate several bars graphs in a loop, and they all resize according to the output size (assume from plot/device size?) rather than according to the bar size. This means that plots with two bars have fat bars, and plots with, say, 6 bars, have thin bars; both outputs are the same size though. The code below represents my script with reproduceable data (I do many other aes/theme changes to mine).

I'd like the output plot to resize (in the dimension of bar width) so that the bars are always the same width across different graphs, but the output images change size according to the number of (same width) bars.

my_factors = c("vs","cyl","carb")

for (current_factor in my_factors) {
    c <- ggplot(mtcars, aes(factor(current_factor)))
    c + geom_bar() + coord_flip()

    ggsave(paste0(my_factors(current_factor),".png")
}

Sorry if I've missed something glaring, I am new to ggplot, and R. I'm from MATLAB so the whole "device" thing still confuses me! In MATLAB I'd specify the bar size explicitly (i.e. not relatively), and the output would resize accordingly.

回答1:

You can use this foo function

library(lazyeval)
library(ggplot2)
foo <- function(data,i, height_rate = 0.1){
  height <- eval(substitute(length(unique(data$i))))
  ld <- as.lazy_dots(list(lazy(i))) 
  ld <- as.lazy_dots(lapply(ld, function(x){ 
    try(x$expr <- as.name(x$expr), silent=TRUE)
    x
  }))
  x <- make_call(quote(aes),make_call(quote(factor),ld))
  ggplot(data, eval(x$expr))+
    geom_bar(width = height_rate*height)+
    coord_flip()
}

foo(mtcars,"cyl")

Because of lazyeval package

foo(mtcars,cyl)

also works.A disadvantage of this code is usage only exact name of column. So in order to use for loop code has to be developed a bit. Hope it helps.