0

As the title suggests, I want to combine stacked and dodge in a barplot. Most answers in Stack Overflow (e.g., this) suggest using facet wrapping. I don't want to do that because I have other graphs that do not use facet wrapping and I don't want the aesthetic to be different. The answer that is the closest to the result I want to achieve is this one. However, I would like to avoid manually creating data frames for all the dodge values.

A subset of the data I'm using is the following.

benchmark <- c("correlation", "correlation", "correlation", "covariance", "covariance", "covariance")
technique <- c("last_value", "dyna", "tage", "last_value", "dyna", "tage")
last_value_predictions <- c(1361, 1336, 453, 1865, 1841, 556)
predictions <- c(0, 25, 908, 0, 24, 1309)
df <- data.frame(benchmark, technique, last_value_predictions, predictions)

I want the benchmarks on the x axis. There should be 3 bars for each benchmark, one for each techniques (dodge). And then each bar should have the predictions stacked on top of the last value predictions.

Any help is appreciated.

vic
  • 359
  • 4
  • 18

1 Answers1

1

I know you do not like the idea of facets, but you can easily adjust the appearance so that they look like a continuous graph, so maybe you could still consider something like this:

benchmark <- rep(c("correlation", "covariance"), each=3)
technique <- rep(c("last_value", "dyna", "tage"), 2)
last_value_predictions <- c(1361, 1336, 453, 1865, 1841, 556)
predictions <- c(0, 25, 908, 0, 24, 1309)
df <- data.frame(benchmark, technique, last_value_predictions, predictions)

library(ggplot2)
library(cowplot)
library(dplyr)
library(tidyr)
pivot_longer(df, ends_with("predictions")) %>% 
    mutate(technique=factor(technique, unique(technique)),
        name=factor(name, rev(unique(name)))) %>% 
    ggplot(aes(x=benchmark, y=value, fill=name)) + 
    geom_col() + 
    theme_cowplot() +
    facet_wrap(.~technique, strip.position = "bottom")+
        theme(strip.background = element_rect(colour=NA, fill="white"), 
            panel.border=element_rect(colour=NA),
            strip.placement = "outside",
            panel.spacing=grid::unit(0, "lines"), 
            legend.position = "bottom") + 
        scale_fill_manual(values=c("blue", "grey"))

Edit: You can, of course, switch benchmark and technique if you want.

Edit #2: Legend adjustment can be achieved by a small extra hack (not sure why it fails otherwise) and labels can be rotated to clean up the appearance of the image result you posted.

p <- pivot_longer(df, ends_with("predictions")) %>% 
    mutate(technique=factor(technique, unique(technique)),
        name=factor(name, rev(unique(name)))) %>% 
    ggplot(aes(x=technique, y=value, fill=name)) + 
    geom_col() + 
    theme_cowplot() +
    facet_wrap(.~benchmark, strip.position = "bottom")+
        theme(strip.background = element_rect(colour=NA, fill="white"), 
            panel.border=element_rect(colour=NA),
            strip.placement = "outside",
            panel.spacing=grid::unit(0, "lines"), 
            legend.position = "bottom",
            axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) + 
        scale_fill_manual(values=c("blue", "grey"))
p2 <- p + theme(legend.position = "none")
leg <- as_grob(ggdraw(get_legend(p), xlim = c(-.5, 1)))
cowplot::plot_grid(p2, leg, nrow = 2, rel_heights = c(1, .1))

Created on 2021-06-25 by the reprex package (v2.0.0)

user12728748
  • 8,106
  • 2
  • 9
  • 14
  • Thanks, this seems very close to my end goal. Is it possible to have the benchmarks on the x axis instead of the techniques? So for example, correlation would have three bars one for each technique. – vic Jun 24 '21 at 20:39
  • Weirdly I'm not getting the same result as you when I substitute technique for benchmark. See the following links. https://i.imgur.com/1vDmDcL.png https://i.imgur.com/qY4Vuz6.png – vic Jun 24 '21 at 23:37
  • Also, why is the legend not centred? I've been trying to fix but I can't figure it out. – vic Jun 25 '21 at 00:07
  • Regarding centering of the legend, see my latest edit for a hack to achieve that. – user12728748 Jun 25 '21 at 11:43