Skip to content

Instantly share code, notes, and snippets.

@AlbertRapp
Last active June 27, 2023 13:01
Show Gist options
  • Save AlbertRapp/cd81e6237fc737c7360080b31d48f7ea to your computer and use it in GitHub Desktop.
Save AlbertRapp/cd81e6237fc737c7360080b31d48f7ea to your computer and use it in GitHub Desktop.
How to split bars instead of stacking them
---
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)
)
```
@KWIZERAL
Copy link

Thank you. This code is great. This is good work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment