library(tidyverse)
library(lubridate)
date <- seq(ymd('2018-08-01'), ymd('2018-08-31'), by = '1 day')
c <- 21.30
x1 <- runif(length(date), 0, 20)
x2 <- rnorm(length(date), 10, 3)
x3 <- abs(rnorm(length(date), 40, 10))
data <- data.frame(c, x1, x2, x3) %>%
t() %>% as.data.frame() %>% rownames_to_column('var')
data <- data %>%
mutate(category1 = c('catA', 'catB', 'catB', 'catC') %>% as.factor(),
category2 = c('catAA', 'catBA', 'catBB', 'catCA') %>% as.factor())
names(data) <- c('var', as.character(date), 'category1', 'category2')
data_long <- data %>%
gather(date, value, -var, -category1, -category2) %>%
mutate(date = ymd(date))
data_long %>%
ggplot(aes(date, value, fill = category1)) +
geom_col(position = 'stack') +
scale_x_date(breaks = '1 week', date_labels = '%Y-%m-%d', expand = c(.01, .01)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
labs(fill = '')
With the example data and code above I generate the following plot:

What I need to do is to remove white spaces between columns. I have found some similar topics, but they recommended use of position_dodge() while it can't be used in my case as I already have position = 'stack', which can't be replaced. How can I make the columns adjacent to each other then?
Edit
Setting width = 1, as proposed by @camille, seems to work ok with the raw data, but not with aggregated to weeks or months - please see the code below:
data_long %>%
mutate(date = floor_date(date, unit = 'week', week_start = 1)) %>%
group_by(category1, date) %>%
summarise(value = sum(value, na.rm = TRUE)) %>%
ungroup() %>%
ggplot(aes(date, value, fill = category1, width = 1)) +
geom_col(position = 'stack') +
scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
labs(fill = '')
Edit 2.
As pointed out by @Camille, width of 1 may refer to 1 day in case of date scale. However, the following doesn't produce expected output and returns warning message: position_stack requires non-overlapping x intervals
data_long %>%
mutate(date = floor_date(date, unit = 'month', week_start = 1)) %>%
group_by(category1, date) %>%
summarise(value = sum(value, na.rm = TRUE),
n = n()) %>%
ungroup() %>%
ggplot(aes(date, value, fill = category1, width = n)) +
geom_col(position = 'stack') +
scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
labs(fill = '')







