How to increase the space between the bars in a bar plot in ggplot2?
Asked Answered
Q

5

72

How can I increase the space between the bars in a bar plot in ggplot2 ?

Quillen answered 13/1, 2011 at 0:26 Comment(2)
could you please provide code example illustrating your problem? In my experience the defaults of ggplot2 are really good, so there should be a good reason to change them.Calvo
Maybe of interest for your specific question? :) #6085738Semination
A
81

You can always play with the width parameter, as shown below:

df <- data.frame(x=factor(LETTERS[1:4]), y=sample(1:100, 4))
library(ggplot2)
ggplot(data=df, aes(x=x, y=y, width=.5)) + 
  geom_bar(stat="identity", position="identity") +
  opts(title="width = .5") + labs(x="", y="") +
  theme_bw()

Compare with the following other settings for width:

alt text

So far, so good. Now, suppose we have two factors. In case you would like to play with evenly spaced juxtaposed bars (like when using space together with beside=TRUE in barplot()), it's not so easy using geom_bar(position="dodge"): you can change bar width, but not add space in between adjacent bars (and I didn't find a convenient solution on Google). I ended up with something like that:

df <- data.frame(g=gl(2, 1, labels=letters[1:2]), y=sample(1:100, 4))
x.seq <- c(1,2,4,5)
ggplot(data=transform(df, x=x.seq), aes(x=x, y=y, width=.85)) +
  geom_bar(stat="identity", aes(fill=g)) + labs(x="", y="") + 
  scale_x_discrete(breaks = NA) + 
  geom_text(aes(x=c(sum(x.seq[1:2])/2, sum(x.seq[3:4])/2), y=0, 
                label=c("X","Y")), vjust=1.2, size=8)

The vector used for the $x$-axis is "injected" in the data.frame, so that so you change the outer spacing if you want, while width allows to control for inner spacing. Labels for the $x$-axis might be enhanced by using scale_x_discrete().

alt text

Aideaidedecamp answered 13/1, 2011 at 8:16 Comment(2)
Apparently, opts is no longer existing in R 4.0 and above.Bollard
As of ggplot 3.0.0, you can use position_dodge2. It takes a padding argument that adds space in between the bars. See my answer below.Loring
A
62

For space between factor bars use

ggplot(data = d, aes(x=X, y=Y, fill=F)) 
 + geom_bar(width = 0.8, position = position_dodge(width = 0.9))

The width in geom_bar controls the bar width in relation to the x-axis while the width in position_dodge control the width of the space given to both bars also in relation to the x-axis. Play around with the width to find one that you like.

Amil answered 24/1, 2013 at 14:22 Comment(0)
L
5

As of ggplot 3.0.0, you can use position_dodge2. It takes a padding argument that adds space in between the bars.

library(ggplot2) # version >= 3.0.0
set.seed(1530676800) # 
tib <- tibble(
  group=rep(LETTERS[1:4], each=3), 
  subgroup=rep(letters[24:26], 4),
  y=sample(1:100, 4*3)
)
ggplot(tib, aes(x=group, fill=subgroup, y=y)) + 
  geom_col(position=position_dodge2()) 

ggplot2 geom_col with position_dodge2 default padding

Default padding is 0.1. Since I know you want to see different padding options:

library(purrr)
library(cowplot)
theme_set(theme_cowplot())

n_col <- 2
bottom_row_starts <- 3
plots0 <- purrr::imap(0.1*c(1:4), \(pad, idx) {
  ret <- ggplot(tib, aes(x=group, fill=subgroup, y=y)) + 
    geom_col(position=position_dodge2(padding=pad)) +
    labs(subtitle=paste0("Padding = ", pad)) #+
    #theme(plot.margin = margin(6, 0, 6, 0))
  if (bottom_row_starts > idx) {
    ret <- ret + xlab(NULL)
  }
  if(1 != (idx %% n_col)) {
    ret <- ret + ylab(NULL)
  }
  return(ret)
})
leg <- cowplot::get_legend(plots0[[1]])

plots <- plots0 %>% purrr::map(\(pp) {
  pp + theme(legend.position="none")
})

cowplot::plot_grid(
  plotlist=plots,
  ncol=n_col
) %>% cowplot::plot_grid(
  leg, 
  rel_widths = c(4, 1)
)

ggplot2 geom_col with position_dodge2 varied padding arranged with cowplot plot_grid

Loring answered 19/9, 2023 at 16:33 Comment(0)
L
3

Thank you very much chl.! I had the same problem and you helped me solving it. Instead of using geom_text to add the X-labels I used scale_x_continuous (see below)

geom_text(aes(x=c(sum(x.seq[1:2])/2, sum(x.seq[3:4])/2), y=0, 
            label=c("X","Y")), vjust=1.2, size=8)

replaced by

scale_x_continuous(breaks=c(mean(x.seq[1:2]), mean(x.seq[3:4])), labels=c("X", "Y")) 
Ludivinaludlew answered 24/4, 2015 at 10:48 Comment(0)
B
1

For space between POSIXlt bars you need adjust the width from the number of seconds in a day

# POSIXlt example: full & half width
d <- data.frame(dates = strptime(paste(2016, "01", 1:10, sep = "-"), "%Y-%m-%d"),
            values = 1:10)

ggplot(d, aes(dates, values)) +
  geom_bar(stat = "identity", width = 60*60*24) 

ggplot(d, aes(dates, values)) +
  geom_bar(stat = "identity", width = 60*60*24*0.5) 
Blodget answered 29/8, 2016 at 13:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.