0

Me and my project partner are trying to create one stacked, horizontal barchart from multiple vertical barcharts as illustrated on the right hand side of the second picture. As of now, we were able to flip our graphs to a horizontal state with the help of this forum: Horizontal Barplot in ggplot2 . However, we are currently stuck at merging multiple horizontal bars into one.

We have currently been trying to implement ways to merge our bars into only one bar in our graphs (and to eventually merge all the graphs into a single one).

However, we could not find examples with datasets similar to ours, nor were we able to implement the posted answers/codes to our dataset/code.

This is our dataset simplfied thanks to an answer from this forum: How to make a great R reproducible example (with libraries included)

library(pdftools)
library(forcats)
library(stringr)
library(showtext)
library(ggplot2)
library(jpeg)
library(png)
library(gridExtra)
library(grid)
library(cowplot)
library(rgdal)
library(rgeos)
library(magick)
library(tidyverse)

ams <- structure(list(segment = c("Allgemein", "Allgemein", "Allgemein","Bundesland", "Bundesland", "Bundesland", "Bundesland", "Sektor","Sektor", "Sektor"),
       group = structure(c(9L, 7L, 18L, 6L, 15L,20L, 21L, 8L, 11L, 17L), levels = c("25 bis 49", "Akad. Ausbildung","Ausländer_innen", "Bau", "Behinderung",
       "Burgenland", "Frauen","Gastronomie", "Gesamt", "Gesundh. Einschr.", "Gesundheitswesen","Handel", "Höhere Ausbildung", "Inländer_innen",
       "Kärnten","Lehrausbildung", "Leiharbeit", "Männer", "Mittlere Ausbildung","Niederösterreich", "Oberösterreich", "Ohne gesundh. Einschr.","Pflichtschule", "Salzburg", "Steiermark", "Tirol", "Über 49","Unter 25", "Verkehr", "Vorarlberg", "Warenherstellung", "Wien"), class = "factor"),
       value = c(319232, 152957, 166275, 8247,18128, 44807, 35270, 42128, 10236, 26847),
       abs_change = c(-17860,-10570, -7290, -544, -3944, -8778, -3329, -4019, 879, -5528),rel_change = c(-5.3, -6.5, -4.2, -6.2, -17.9, -16.4, -8.6,-8.7, 9.4, -17.1),
       rel_change2 = c("-5,3%", "-6,5%", "-4,2%","-6,2%", "-17,9%", "-16,4%", "-8,6%", "-8,7%", "+9,4%", "-17,1%"),
       abs_change_vj = c(-21910, -13342, -8568, -757, -1185,-5927, -2205, -471, -934, -4421), rel_change_vj = c(-6.4,-8, -4.9, -8.4, -6.1, -11.7, -5.9, -1.1, -8.4, -14.1),
       rel_change2vj = c("-6,4%","-8%", "-4,9%", "-8,4%", "-6,1%", "-11,7%", "-5,9%", "-1,1%","-8,4%", "-14,1%"),
       color = c("#CEDE8C", "#CEDE8C", "#CEDE8C","#CEDE8C", "#CEDE8C", "#CEDE8C", "#CEDE8C", "#CEDE8C", "#EE7F74","#CEDE8C"),
       colorvj = c("#CEDE8C", "#CEDE8C", "#CEDE8C","#CEDE8C", "#CEDE8C", "#CEDE8C", "#CEDE8C", "#CEDE8C", "#CEDE8C","#CEDE8C"),
       abs_change2 = c("-17.860", "-10.570", "-7.290","-544", "-3.944", "-8.778", "-3.329", "-4.019", "879", "-5.528"),
       abs_change2vj = c("-21.910", "-13.342", "-8.568", "-757","-1.185", "-5.927", "-2.205", "-471", "-934", "-4.421")), row.names = c(1L,2L, 3L, 4L, 5L, 6L, 7L, 30L, 31L, 32L), class = "data.frame")

And here is an example of the code which produces one of our current bar graphs:

allgemein3 <- 
  ggplot(data = ams %>% 
           filter(segment == "Allgemein") %>% 
           # filters data that's not allgemein (general)
           mutate(group = fct_relevel(group, "Männer", "Frauen", "Gesamt")), 
           # reorders sequence of "group" data in ams
         aes(x = group, y = abs_change, fill = color)) + 
         # designates axis name and color
  geom_bar(position = "stack", stat = "identity", width = 0.55) +
  scale_fill_identity(guide = FALSE) +
  geom_hline(yintercept = 0) +
  coord_flip()

allgemein3

And this is the resulted bar graph: https://drive.google.com/file/d/1Uj_vWtuRtxiuIny6WT4_2s_V_07LGvaD/view?usp=sharing

And this illistrates the graphs in their original form (left hand side) and the graph which we desired (right hand side): https://drive.google.com/file/d/1P_2411HvTYB1OlXQCFbW_48_XzyHfILO/view?usp=share_link

This is our session info:

─ Session info ────────────────────────────────────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.2.1 (2022-06-23)
 os       macOS Ventura 13.0
 system   x86_64, darwin17.0
 ui       RStudio
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       Europe/Vienna
 date     2022-11-10
 rstudio  2021.09.2+382 Ghost Orchid (desktop)
 pandoc   2.14.0.3 @ /Applications/RStudio.app/Contents/MacOS/pandoc/ (via rmarkdown)

Any solution or advice will be greatly appreciated! Please let us know any questions you have.

1 Answers1

2

The quick and easy option would be to map your segments on the y axis and fill by group. The drawback is that you end up with one legend for all segments, even if there are some options like ggnewscale to get separate legends:

library(tidyverse)

ams_filtered <- ams %>%
  filter(group != "Gesamt") %>%
  mutate(group = fct_inorder(factor(group)),
         segment = fct_rev(segment))

ggplot(data = ams_filtered, aes(x = abs_change, y = segment, fill = group)) + 
  geom_col(width = 0.55) +
  geom_vline(xintercept = 0) +
  labs(x = NULL, y = NULL, fill = NULL)

enter image description here

A second option would be to create separate plots which you could glue together using e.g. patchwork. To make my life easier I use a plotting function. However the same approach works if you create your plots one by one:

plot_fun <- function(.data, limits = NULL) {
  ggplot(data = .data, aes(x = abs_change, y = segment, fill = group)) + 
    geom_col(width = 0.55) +
    geom_vline(xintercept = 0) +
    scale_x_continuous(limits = limits) +
    labs(x = NULL, y = NULL, fill = NULL)
}

limits <- range(ams$abs_change)

ams_split <- split(ams_filtered, ams_filtered$segment)

plot_list <- purrr::map(ams_split, plot_fun, limits = limits)

library(patchwork)

wrap_plots(plot_list, ncol = 1)

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51