Skip to content

Instantly share code, notes, and snippets.

@bjulius
Created April 16, 2025 23:17
Show Gist options
  • Select an option

  • Save bjulius/1c5c32b14029cbac0815ec3370ae791e to your computer and use it in GitHub Desktop.

Select an option

Save bjulius/1c5c32b14029cbac0815ec3370ae791e to your computer and use it in GitHub Desktop.
ggplot2 R Code for Horizontal Waterfall Chart
library(tidyverse)
library(patchwork)
library(ggtext)
# Create the data frame
df <- data.frame(
category = c(
"Machine sales", "Accessories sales", "Sales",
"Cost of sales", "Gross profit", "R&D costs",
"Sales costs", "Administration costs", "Net income"
),
value = c(1529, 468, 1997, -1011, 986, -200, -359, -170, 257)
)
# Identify total/subtotal rows according to IBCS
subtotal_categories <- c("Sales", "Gross profit", "Net income")
df$is_total <- df$category %in% subtotal_categories
# Prepare data for waterfall - Calculate cumulative sums
df <- df %>%
mutate(
end = cumsum(value),
start = lag(end, default = 0),
type = case_when(
is_total ~ "total",
value >= 0 ~ "increase",
value < 0 ~ "decrease"
),
ypos = n():1,
label_value = abs(value)
)
# Define IBCS colors
ibcs_colors <- c(
increase = "#BBBBBB",
decrease = "#333333",
total = "#FFFFFF"
)
ibcs_outline_colors <- c(
increase = NA,
decrease = NA,
total = "#000000"
)
# Horizontal waterfall chart with label extensions
p1 <- ggplot(df, aes(y = ypos)) +
geom_vline(xintercept = 0, linewidth = 0.5) +
geom_rect(aes(
xmin = start, xmax = end,
ymin = ypos - 0.35, ymax = ypos + 0.35,
fill = type, color = type
), linewidth = ifelse(df$is_total, 0.7, 0)) +
geom_text(aes(
x = end + ifelse(value >= 0, 40, -40),
label = label_value
),
hjust = ifelse(df$value >= 0, 0, 1),
size = 3.5, color = "black", vjust = 0.5) +
scale_y_continuous(
breaks = df$ypos,
labels = df$category,
expand = expansion(add = c(0.5, 0.5))
) +
scale_x_continuous(
labels = NULL, name = NULL,
expand = expansion(mult = c(0.1, 0.2))
) +
scale_fill_manual(values = ibcs_colors, guide = "none") +
scale_color_manual(values = ibcs_outline_colors, guide = "none") +
coord_cartesian(clip = "off") + # extend labels beyond plot
theme_minimal() +
theme(
panel.grid = element_blank(),
axis.text.y = element_text(size = 10, color = "black"),
axis.text.x = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
plot.margin = margin(t = 10, r = 60, b = 20, l = 20) # tighten top margin, expand right
)
# Annotated layout with markdown subtitle and tighter spacing
combined_plot <- p1 +
plot_annotation(
title = "Alpha Corporation",
subtitle = "**Income Statement** in mUSD<br>Q2 2019",
theme = theme(
plot.title = element_text(size = 12, hjust = 0, margin = margin(b = 2)),
plot.subtitle = ggtext::element_markdown(size = 10, hjust = 0, lineheight = 1.05),
plot.margin = margin(t = 5, b = 10)
)
)
# Display
combined_plot
@bjulius
Copy link
Copy Markdown
Author

bjulius commented Apr 16, 2025

horizontal waterfall

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