I'm creating a bar chart with a pattern for a subset of the bars, and I want to add error bars.
However, I'm having trouble lining up the error bars with with the bar charts—I want to have them appear centered on each bar. How do I do this? Moreover, the legend currently does not clearly distinguish the striped and non-striped bars as corresponding to not treated and treated groups.
Finally, I'd like to create version of this plot which stacks adjacent bars (i.e. bars within each facet_grid)—any tips on how to do that would be much appreciated.
The code I'm using is:
library(ggplot2)
library(tidyverse)
library(ggpattern)
models = c("a", "b")
task = c("1","2")
ratios = c(0.3, 0.4)
standard_errors = c(0.02, 0.02)
ymax = ratios standard_errors
ymin = ratios - standard_errors
colors = c("#F39B7FFF", "#8491B4FF")
df <- data.frame(task = task, ratios = ratios)
df <- df %>% mutate(filler = 1-ratios)
df <- df %>% gather(key = "obs", value = "ratios", -1)
df$upper <- df$ratios c(standard_errors,standard_errors)
df$models <- c(models,models)
df$lower <- df$ratios - c(standard_errors,standard_errors)
df$col <- c(colors,colors)
df$group <- paste(df$task, df$models, sep="-")
df$treated <- "yes"
df[df$ratios<0.5,]$treated = "no"
p <- ggplot(df, aes(x = group, y = ratios, fill = col, ymin = lower, ymax = upper))
stat_summary(aes(pattern=treated),
fun = "mean", position=position_dodge(),
geom = "bar_pattern", pattern_fill="black", colour="black")
geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.2, position=position_dodge(0.9))
scale_pattern_manual(values=c("none", "stripe")) #edited part
facet_grid(.~task,
scales = "free_x", # Let the x axis vary across facets.
space = "free_x", # Let the width of facets vary and force all bars to have the same width.
switch = "x") guides(colour = guide_legend(nrow = 1))
guides(fill = "none")
p
CodePudding user response:
Here is an option
df %>%
ggplot(aes(x = models, y = ratios))
geom_col_pattern(
aes(fill = col, pattern = treated),
pattern_fill = "black",
colour = "black",
pattern_key_scale_factor = 0.2,
position = position_dodge())
geom_errorbar(
aes(ymin = lower, ymax = upper, group = interaction(task, treated)),
width = 0.2,
position = position_dodge(0.9))
facet_grid(~ task, scales = "free_x")
scale_pattern_manual(values = c("none", "stripe"))
scale_fill_identity()
A few comments:
- I don't understand the point of creating
group
. IMO this is unnecessary. TBH, I also don't understand the point ofmodels
andtask
: if task = "1" then models = "a"; if task = "2" then models = "b"; so task and models are redundant as they encode the same thing (whether you call it "1"/"2" or "a"/"b"). - The reason why you (originally) didn't see a pattern in the legend is because of the scale factor in the legend key. As per
?scale_col_pattern
, you can adjust this with thepattern_key_scale_factor
parameter. Here, I've chosenpattern_key_scale_factor = 0.2
but you may want to play with different values. - The reason why the error bars didn't align with the dodged bars was because
geom_errorbar
didn't know that there are differenttask
-treated
combinations. We can fix this by explicitly defining agroup
aesthetic given by the combination oftask
&treated
values. The reason why you don't need this ingeom_col_pattern
is because you already allow for differenttreated
values through thepattern
aesthetic. - You want to use
scale_fill_identity()
if you already have actual colour values defined in thedata.frame
.