How can I increase the space between the bars in a bar plot in ggplot2 ?
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
:
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()
.
opts
is no longer existing in R 4.0 and above. –
Bollard position_dodge2
. It takes a padding
argument that adds space in between the bars. See my answer below. –
Loring 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.
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())
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)
)
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"))
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)
© 2022 - 2024 — McMap. All rights reserved.