boboppp
boboppp

Reputation: 1

ggplot2 - 100% stacked bar chart with variable width bars but no space gap or overlap

I have a 100% stacked bar chart with variable width bars, but I would like for there to be no space gaps between the bars or overlap between the bars. Here is my sample data and output without the scale_x_continuous line.


output chart

library(ggplot2)

df <- data.frame(x = c("A","A","B","B","C","C"), group = c("L","R","L","R","L","R"),width = c(0.1,0.1,0.50,0.50,0.40,0.40), y = c(0.75,0.25,0.5,0.5,0.9,0.1))

pos <- 0.5 * (cumsum(df$width) + cumsum(c(0, df$width[-length(df$width)])))


g <-ggplot(df, aes(x = x, y = y, width = width*2, fill = group)) + 
    geom_bar(stat = "identity", color = "white" ) +
    scale_x_continuous(breaks = pos)
g

I have referenced the following threads and wasn't able to get the solutions to work for my scenario:

How to make variable bar widths in ggplot2 not overlap or gap

Spineplots in ggplot or at least vertical labels

The 1st link isnt using a stacked chart, but solves for the gap issue on a standard bar chart. The 2nd link is exactly what I am looking for, but I cant recreate the solution with my sample data. Am I missing something obvious?

Upvotes: 0

Views: 213

Answers (1)

The margin space over and around plots is controlled by the expansion argument of the scale_y_x() functions (in your case, scale_y_continuous and scale_x_discrete). It's called expansion because it's a multiplicative factor that adds space on top and below the bars, so setting the expansion to 0 will remove any extra space around your plot. Therefore, you can remove this expansion margin like this:

library(ggplot2)

df <- data.frame(x = c("A","A","B","B","C","C"), group = c("L","R","L","R","L","R"),width = c(0.1,0.1,0.50,0.50,0.40,0.40), y = c(0.75,0.25,0.5,0.5,0.9,0.1))

pos <- 0.5 * (cumsum(df$width) + cumsum(c(0, df$width[-length(df$width)])))


ggplot(df, aes(x = x, y = y, width = width*2, fill = group)) + 
  geom_bar(stat = "identity", color = "white") +
  scale_y_continuous(expand = expansion(0)) +
  scale_x_discrete(expand = expansion(0))

Example result

EDIT: To get the bars to touch each other, i.e., to plot bars that have no horizontal space between them, we can calculate their position on the x axis as follows:

library(dplyr)
library(ggplot2)

df <- data.frame(x = c("A","A","B","B","C","C"), group = c("L","R","L","R","L","R"),width = c(0.1,0.1,0.50,0.50,0.40,0.40), y = c(0.75,0.25,0.5,0.5,0.9,0.1))

df2 <- df |> 
  mutate(id = as.factor(x) |> as.numeric()) |> 
  mutate(x2 = id * (2-width))

ggplot(df2, aes(x = x2, y = y,  width = width*4, fill = group)) + 
  geom_bar(stat = "identity", color = "white") +
  scale_y_continuous(expand = expansion(0)) +
  scale_x_continuous(labels = df2$x, breaks = df2$x2, expand = expansion(0))

enter image description here

Upvotes: 0

Related Questions