Reputation: 4096
I have some data (x
) I'd like to plot as a histogram. There are two sample types (s
), and each sample was collected in two different ways (r
).
I would like to plot them as a stacked histogram filled by both s
and r
-- the best way to do it would be to facet them as per my my last example, but I am space-limited.
I can plot the data filled by s
using a single geom_histogram
. I can plot two geom_histogram
s to plot the different r
. I don't know how to make the different geoms stack though. I haven't figured out how to fill them, but ggnewscale is probably an option.
I'd like to choose fills such as (for example) s
== red, blue, and r
== light, dark of the respective s
colour.
Any suggestions?
library(tidyverse)
library(tibble)
x <- c(0,0,0,0,0,1,1,1,1,-1,-1,-1,-1,2,2,2,-2,-2,-2,3,3,-3,-3,4,-4, 8,8,8,8,8,9,9,9,9,9,7,7,7,10,10,10,6,6,6,11,11,5,5,12,4)
r <- as.factor(c(1,2,2,2,1,1,2,2,2, 1, 1, 2, 2,2,2,2, 1, 1, 2,2,2, 2, 2,2, 2, 1,1,2,2,2,1,1,1,2,1,1,2,2, 1, 2, 2,2,2,2, 2, 1,1,2, 1,1))
s <- c(rep.int("a", 25), rep.int("b", 25))
figsd <- tibble(x,r,s)
figsd %>%
ggplot(aes(x=x)) +
geom_histogram(aes(fill = s), binwidth = 1, position = "stack") +
coord_cartesian(ylim = c(0,5))
figsd %>%
ggplot(aes(x=x)) +
geom_histogram(data = . %>% filter(r == 1), aes(fill = s), binwidth = 1,alpha = 0.5, position = "stack") +
geom_histogram(data = . %>% filter(r != 1), aes(fill = s), binwidth = 1,alpha = 0.5, position = "stack") +
coord_cartesian(ylim = c(0,5))
figsd %>%
ggplot(aes(x=x)) +
geom_histogram(aes(fill = r), binwidth = 1,position = "stack") +
coord_cartesian(ylim = c(0,5)) +
facet_grid(s ~ .)
Created on 2020-11-02 by the reprex package (v0.3.0)
Upvotes: 0
Views: 992
Reputation: 4096
Taken from the comment of @alistaire.
Redid ordering and colouring to make it a little better.
library(tidyverse)
library(tibble)
x <- c(0,0,0,0,0,1,1,1,1,-1,-1,-1,-1,2,2,2,-2,-2,-2,3,3,-3,-3,4,-4, 8,8,8,8,8,9,9,9,9,9,7,7,7,10,10,10,6,6,6,11,11,5,5,12,4)
r <- as.factor(c(1,2,2,2,1,1,2,2,2, 1, 1, 2, 2,2,2,2, 1, 1, 2,2,2, 2, 2,2, 2, 1,1,2,2,2,1,1,1,2,1,1,2,2, 1, 2, 2,2,2,2, 2, 1,1,2, 1,1))
s <- c(rep.int("a", 25), rep.int("b", 25))
figsd <- tibble(x,r,s)
figsd %>% mutate(r = factor(r, levels=c(2, 1))) %>%
ggplot(aes(x=x)) +
geom_histogram(aes(fill = interaction(r,s)), binwidth = 1, position = "stack")+
scale_fill_manual(breaks = c("1.a","2.a","1.b","2.b"),
values = c('1.a' = 'lightblue', '1.b' = 'pink', '2.a' = 'darkblue', '2.b' = 'darkred'),
labels = c("1.a","2.a","1.b","2.b")
) +
coord_cartesian(ylim = c(0,5))
Created on 2020-11-02 by the reprex package (v0.3.0)
Upvotes: 1
Reputation: 43334
You can create an interaction between the two groupings and pass that to the fill
aesthetic:
library(ggplot2)
figsd <- data.frame(
x = c(0,0,0,0,0,1,1,1,1,-1,-1,-1,-1,2,2,2,-2,-2,-2,3,3,-3,-3,4,-4, 8,8,8,8,8,9,9,9,9,9,7,7,7,10,10,10,6,6,6,11,11,5,5,12,4),
r = as.factor(c(1,2,2,2,1,1,2,2,2, 1, 1, 2, 2,2,2,2, 1, 1, 2,2,2, 2, 2,2, 2, 1,1,2,2,2,1,1,1,2,1,1,2,2, 1, 2, 2,2,2,2, 2, 1,1,2, 1,1)),
s = c(rep.int("a", 25), rep.int("b", 25))
)
ggplot(figsd, aes(x, fill = interaction(r, s))) +
geom_histogram(binwidth = 1) +
scale_fill_manual(values = c(
'1.a' = 'lightblue',
'1.b' = 'darkblue',
'2.a' = 'pink',
'2.b' = 'darkred'
)) +
labs(fill = 'group')
Levels here don't inherently mean anything, so you'll likely want to set fill colors deliberately to show relationships.
Also note that interaction()
doesn't scale well, for whatever reason—if you're dealing with 100k rows, paste()
will be considerably faster even though interaction()
is more semantically correct in terms of what you're trying to display.
Upvotes: 3