Reputation: 685
I need to create a stacked bar chart of the relative proportion, scaled to the x variable. Here's what I mean.
With a dataframe something like this:
df <- data.frame(foo = rep(1:5,500), bar = as.factor(c(rep("a",100), rep("b",100), rep("c",100), rep("d",100), rep("e",100))), baz = c(rep("R", 5*250), rep("CRAN", 5*250)), val = rbinom(5*500,1,0.1))
I need to create a plot that combines the following two plots. I need the shape of the second plot and the bar colour coding of the first plot (scaled to the second plot. Ideally I would also plot a density over it (like the first plot).
library(ggplot2)
ggplot(subset(df, val == 1), aes(x = foo)) + geom_bar(aes(fill = bar), position = "fill") + scale_fill_brewer(type = "div", palette = 8, direction = 1) + facet_wrap(~baz) + geom_density(aes(foo))
ggplot(subset(df, val == 1), aes(x = foo, y = as.factor(foo))) + geom_col(position = "identity") + scale_fill_brewer(type = "div", palette = 8, direction = 1) + facet_wrap(~baz)
The end result should be like the facet on the left (on the image below).
How do I do this in ggplot2?
Upvotes: 1
Views: 528
Reputation: 685
This is the solution that I came up with:
df <- data.frame(foo = rep(1:5,500), bar = as.factor(c(rep("a",100), rep ("b",100), rep("c",100), rep("d",100), rep("e",100))), baz = c(rep("R", 5*250), rep("CRAN", 5*250)), val = rbinom(5*500,1,0.1))
p <- ggplot(subset(df, val == 1), aes(x = foo)) + geom_bar(aes(fill = bar), position = "fill") + scale_fill_brewer(type = "div", palette = 8, direction = 1) + facet_wrap(~baz)
p1 <- ggplot(subset(df, val == 1), aes(x = foo, y = as.factor(foo))) + geom_col(position = "identity") + scale_fill_brewer(type = "div", palette = 8, direction = 1) + facet_wrap(~baz)
z <- ggplot_build(p)
z1 <-ggplot_build(p1)
z$data[[1]]$ymin <- z$data[[1]]$ymin*z$data[[1]]$x
z$data[[1]]$ymax <- z$data[[1]]$ymax*z$data[[1]]$x
z$data[[1]]$y <- z$data[[1]]$y*z$data[[1]]$x
z$layout$panel_ranges <- z1$layout$panel_ranges
plot(ggplot_gtable(z))
Here's what it looks like:
This works, but I'm open to other (less hacked together) solutions.
Upvotes: 0
Reputation: 28339
Maybe something like this would work: In geom_bar()
added stat = "identity"
and removed fill = "position"
. And you can replace density with histogram (which is basically the same density).
ggplot(subset(df, val == 1), aes(foo)) +
geom_bar(aes(y = foo, fill = bar), stat = "identity") +
geom_histogram(aes(foo), color = "black") +
facet_wrap( ~ baz) +
scale_fill_brewer(type = "div", palette = 8, direction = 1) +
labs(x = NULL, y = NULL) +
theme(legend.position = "bottom")
Upvotes: 1
Reputation: 6222
How about
library(gridExtra)
grid.arrange(p1, p2, ncol=1)
where p1
and p2
are the two ggplots.
p1 <- ggplot(subset(df, val == 1), aes(x = foo)) + geom_bar(aes(fill = bar),
position = "fill") + scale_fill_brewer(type = "div", palette = 8,
direction = 1) + facet_wrap(~baz) + geom_density(aes(foo))
p2 <- ggplot(subset(df, val == 1), aes(x = foo, y = as.factor(foo))) +
geom_col(position = "identity") + scale_fill_brewer(type = "div",
palette = 8, direction = 1) + facet_wrap(~baz)
Upvotes: 1