I did find something about this for numeric values (ggplot bar chart with two dataframes) as well as date, but not for categorical, so I'm having issues.
I would like "grade" to be the stack, and then have the two groups next to each other at each x-axis point.
library(ggplot2)
data <- data.frame('group'=c(rep('g1',50), rep('g2',50)),
'grade'=c(rep('1-2',20), rep('3-4',40),
rep('1-2',35), rep('3-4',5)),
'problem'=c(rep('p1',5), rep('p2',52),
rep('p3',29), rep('p4',14)))
This is what I'm using to just do the grade part, with descending frequency
ggplot(data, aes(fill=grade, x=reorder(problem, problem,
function(x)-length(x)))) +
geom_bar(aes(y = (..count..)/sum(..count..)))
I tried this based on the link provided, but it doesn't work because problem isn't numeric
ggplot(mapping=aes(x=problem)) +
geom_bar(data=data1, aes(x=problem-0.1), fill="red", binwidth=0.1) +
geom_bar(data=data2, fill="blue", binwidth=0.1)
Should I just map problem to numeric, and then relabel it, or is there a way to do an offset for a category? There was also an example using dates (geom_bar(): stacked and dodged combined) where the shift works, presumably because dates have numeric equivalents.
I shuffled the group
column to showcase the solution better; here's the plot for the original data.
library(ggplot2)
set.seed(42)
data <- data.frame(group = sample(c(rep('g1', 50), rep('g2', 50))),
grade = c(rep('1-2', 20), rep('3-4', 40),
rep('1-2', 35), rep('3-4', 5)),
problem = c(rep('p1', 5), rep('p2', 52),
rep('p3', 29), rep('p4', 14)))
within(data,
xdoge <- as.integer(reorder(problem, problem,
function(x) -length(x))) +
0.4 * scale(as.numeric(as.factor(group)), scale = FALSE)) |>
ggplot(aes(x = xdoge)) +
geom_bar(aes(color = group, y = after_stat(count)/sum(after_stat(count))),
width = 0.35, size = 2, fill = NA) +
geom_bar(aes(fill = grade, y = after_stat(count)/sum(after_stat(count))),
width = 0.35) +
scale_x_continuous(breaks = seq_along(unique(data$problem)),
labels = levels(reorder(data$problem, data$problem,
function(x) -length(x)))) +
scale_colour_grey(start = 0.4, end = 0.8) +
theme_bw() +
labs(x = "Problem", y = "Proportion",
fill = "Grade", color = "Group")
Note that dot-dot notation is deprecated. Use after_stat
.
Created on 2025-07-25 with reprex v2.1.1