Last active
June 27, 2023 13:01
-
-
Save AlbertRapp/cd81e6237fc737c7360080b31d48f7ea to your computer and use it in GitHub Desktop.
How to split bars instead of stacking them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
output: html_document | |
editor_options: | |
chunk_output_type: console | |
--- | |
```{r} | |
setwd(here::here('stacked_bar_alternative/')) | |
camcorder::gg_record( | |
dir = 'img', | |
height = 16, | |
width = 16, | |
unit = 'cm', | |
dpi = 300 | |
) | |
``` | |
# Packages, Sizes, Fonts and Colors | |
```{r} | |
library(tidyverse) | |
library(patchwork) | |
# General | |
text_color <- 'grey40' | |
font_family <- 'Fira Sans' | |
color_palette <- viridisLite::mako(6)[-c(1, 6)] | |
font_size <- 7 | |
grid_color <- 'grey70' | |
grid_style <- 3 | |
# Legend | |
legend_width_cm <- 0.4 | |
legend_font_size <- 6 | |
# Titles | |
title_color <- text_color | |
title_font_family <- 'Merriweather' | |
title_size <- 18 | |
smaller_title_size <- 11 | |
# Caption | |
caption_color <- text_color | |
caption_font_family <- font_family | |
caption_size <- 7 | |
``` | |
# Create data for bar charts | |
```{r} | |
mpg_2008 <- mpg %>% | |
filter( | |
year == 2008, | |
!(class %in% c('2seater', 'minivan')) | |
) %>% | |
mutate( | |
class = case_when( | |
class %in% c('compact', 'subcompact') ~ '(Sub-)Compact', | |
class %in% c('pickup', 'suv') ~ 'Pickup/SUV', | |
T ~ str_to_title(class) | |
), | |
manufacturer = str_to_title(manufacturer), | |
manufacturer = fct_infreq(manufacturer) %>% fct_rev() | |
) | |
``` | |
# Stacked bar plot | |
```{r} | |
unsplit_plot <- mpg_2008 %>% | |
ggplot(aes(y = manufacturer, fill = class)) + | |
geom_bar(position = position_stack(reverse = T)) + | |
scale_fill_manual(values = color_palette) + | |
scale_x_continuous(expand = expansion(mult = c(0, 0.1))) + | |
scale_y_discrete(expand = expansion(mult = 0)) + | |
geom_vline(xintercept = 0, size = 1) + | |
theme_minimal() + | |
theme( | |
plot.title = element_text( | |
family = font_family, | |
color = text_color, | |
size = smaller_title_size | |
), | |
axis.text = element_text( | |
family = font_family, | |
color = text_color, | |
size = font_size | |
), | |
strip.text = element_text( | |
color = text_color, | |
hjust = 0, | |
margin = margin(l = -0.5, b = 5) | |
), | |
legend.key.size = unit(legend_width_cm, 'cm'), | |
legend.text = element_text( | |
family = font_family, | |
color = text_color, | |
size = legend_font_size | |
), | |
legend.title = element_text( | |
family = font_family, | |
color = text_color, | |
size = legend_font_size | |
), | |
legend.margin = margin(), | |
legend.position = 'top', | |
plot.title.position = 'plot', | |
panel.grid.minor = element_blank(), | |
panel.grid.major.y = element_blank(), | |
panel.grid.major = element_line(size = 0.5, linetype = grid_style, color = grid_color) | |
) + | |
labs( | |
x = element_blank(), | |
y = element_blank(), | |
fill = element_blank(), | |
title = 'Number of car manufacturers (stacked by car classes)' | |
) | |
``` | |
# Split Plot | |
## Split classes | |
```{r} | |
class_plots <- mpg_2008 %>% | |
ggplot(aes(y = manufacturer, fill = class)) + | |
geom_bar() + | |
scale_fill_manual(values = color_palette) + | |
facet_wrap(vars(class)) + | |
scale_x_continuous(expand = expansion(mult = c(0, 0.1))) + | |
scale_y_discrete(expand = expansion(mult = 0)) + | |
geom_vline(xintercept = 0, size = 1) + | |
theme_minimal() + | |
theme( | |
axis.text = element_text( | |
family = font_family, | |
color = text_color, | |
size = font_size | |
), | |
strip.text = element_text( | |
color = text_color, | |
hjust = 0, | |
margin = margin(l = -0.5, b = 5) | |
), | |
legend.position = 'none', | |
panel.grid.minor = element_blank(), | |
panel.grid.major.y = element_blank(), | |
panel.grid.major = element_line(size = 0.5, linetype = grid_style, color = grid_color) | |
) + | |
labs(x = element_blank(), y = element_blank()) | |
``` | |
## Create a bar chart for totals | |
```{r} | |
total_plot <- mpg_2008 %>% | |
ggplot(aes(y = manufacturer)) + | |
geom_bar(fill = color_palette[4]) + | |
scale_x_continuous(expand = expansion(mult = c(0, 0.1))) + | |
scale_y_discrete(expand = expansion(mult = 0)) + | |
geom_vline(xintercept = 0, size = 1) + | |
facet_wrap(vars('Total')) + | |
theme_minimal() + | |
theme( | |
axis.text = element_text( | |
family = font_family, | |
color = text_color, | |
size = font_size | |
), | |
strip.text = element_text( | |
color = text_color, | |
hjust = 0, | |
margin = margin(l = -0.5, b = 5) | |
), | |
legend.position = 'none', | |
axis.text.y = element_blank(), | |
panel.grid.minor = element_blank(), | |
panel.grid.major.y = element_blank(), | |
panel.grid.major = element_line(size = 0.5, linetype = grid_style, color = grid_color) | |
) + | |
labs( | |
x = element_blank(), | |
y = element_blank(), | |
) | |
``` | |
## Arrange classes and totals with {patchwork} | |
```{r} | |
split_plot <- wrap_elements( | |
plot = class_plots + | |
total_plot + | |
plot_layout(widths = c(0.75, 0.25)) + | |
plot_annotation( | |
title = 'Number of car manufacturers (split by car class)', | |
theme = theme( | |
plot.title = element_text( | |
family = font_family, | |
color = text_color, | |
size = smaller_title_size | |
) | |
) | |
) & | |
theme( | |
plot.margin = margin(), | |
plot.background = element_rect(fill = viridisLite::mako(6)[6], color = NA) | |
) | |
) | |
``` | |
# Put together comparison with {patchwork} | |
```{r} | |
unsplit_plot / | |
plot_spacer() / | |
split_plot + | |
plot_annotation( | |
title = 'Splitting stacked bar plots gives each group a\nreference line for easier comparisons', | |
caption = 'Data: {ggplot2} R package | Graphic: Albert Rapp @rappa753', | |
theme = theme( | |
plot.title = element_text( | |
size = title_size, | |
family = title_font_family, | |
color = title_color, | |
face = 'bold', | |
lineheight = 1 | |
), | |
plot.caption = element_text( | |
size = caption_size, | |
family = caption_font_family, | |
color = caption_color | |
) | |
) | |
) + | |
plot_layout(heights = c(0.425, 0.01, 0.575)) & | |
theme( | |
plot.background = element_rect(fill = viridisLite::mako(6)[6], color = NA) | |
) | |
``` | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you. This code is great. This is good work