Waterfall Plot

Authors

[Editor] Shixiang Wang;

[Contributors] ZCode (GLM) โ€” AI-generated, independently AI-reviewed.

Modified

2026-10-29

๐Ÿค– AI Skill โ€” Download the Bizard unified skill for your AI assistant โฌ‡๏ธ Download Skill ZIP
๐Ÿ”Œ MCP Server โ€” Let AI agents (Claude Code, Cursor, โ€ฆ) query Bizard live: claude mcp add bizard -- npx @openbiox/bizard-mcp โ€” or the free hosted instance (no install, faster from mainland China): claude mcp add --transport http bizard http://biotree.top:38123/bizard-mcp/mcp ๐Ÿ“– MCP Docs
๐Ÿ“– Cite Bizard โ€” if Bizard helps your research, please cite: Li, K., Zheng, H., Huang, K., et al. (2026). Bizard: A Community-Driven Platform for Accelerating and Enhancing Biomedical Data Visualization. iMetaMed, e70038. ๐Ÿ”— DOI / BibTeX

The waterfall plot is the standard way to display best tumor response per patient in oncology trials. Each bar is one patient, sorted by the best percentage change in the sum of target-lesion diameters from baseline; bars are typically colored by the RECIST response category (CR, PR, SD, PD) [1]. The plot answers โ€œhow deep are the responses?โ€ at a glance, complements the Kaplan-Meier survival curves (which answer โ€œhow long did patients live?โ€), and is often paired with a spider plot showing each patientโ€™s longitudinal tumor-size trajectory.

Note

Waterfall plots can visually overestimate the response rate because only the best change is displayed and non-measurable progressions may be under-represented [2]. Pair them with spider plots and report the response rate in numbers.

Example

WaterfallPlot DEMO

Setup

  • System Requirements: Cross-platform (Linux/MacOS/Windows)

  • Programming language: R

  • Dependent packages: dplyr; forcats; ggplot2; patchwork

# Load packages
library(dplyr)
library(forcats)
library(ggplot2)
library(patchwork)
sessioninfo::session_info("attached")
โ”€ Session info โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 setting  value
 version  R version 4.6.1 (2026-06-24)
 os       Ubuntu 24.04.5 LTS
 system   x86_64, linux-gnu
 ui       X11
 language (EN)
 collate  C.UTF-8
 ctype    C.UTF-8
 tz       UTC
 date     2026-10-29
 pandoc   3.1.3 @ /usr/bin/ (via rmarkdown)
 quarto   1.10.19 @ /usr/local/bin/quarto

โ”€ Packages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 ! package   * version    date (UTC) lib source
 P dplyr     * 1.2.1      2026-04-03 [?] RSPM
 P forcats   * 1.0.1      2025-09-25 [?] RSPM
 P ggplot2   * 4.0.3.9000 2026-10-26 [?] Github (tidyverse/ggplot2@b638d65)
 P patchwork * 1.3.2      2025-08-25 [?] RSPM

 [1] /home/runner/.cache/R/renv/library/Bizard-5140bdc6/linux-ubuntu-noble/R-4.6/x86_64-pc-linux-gnu
 [2] /home/runner/work/_temp/Library
 [3] /opt/R/4.6.1/lib/R/library

 * โ”€โ”€ Packages attached to the search path.
 P โ”€โ”€ Loaded and on-disk path mismatch.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Data Preparation

The required input is one row per patient with, at minimum, the best percentage change in target-lesion size and the RECIST category. Because no clinical-trial patient-level data set ships with R, we simulate a realistic phase-II-style cohort: 40 patients whose best change follows the expected pattern of a moderately active regimen (RECIST thresholds: PR requires โ‰ฅ30% shrinkage, PD โ‰ฅ20% growth) [1]. Replace the simulation with read.csv("your_recist_data.csv") for real data โ€” the column structure is identical.

set.seed(2026)
n <- 40

response <- sample(c("CR", "PR", "SD", "PD"), n,
                   prob = c(0.05, 0.40, 0.30, 0.25), replace = TRUE)
best_change <- round(case_when(
  response == "CR" ~ -runif(n, 95, 100),   # complete response: almost full shrinkage
  response == "PR" ~ -runif(n, 30, 92),    # partial response: 30-90% shrinkage
  response == "SD" ~ runif(n, -25, 18),    # stable disease
  response == "PD" ~ runif(n, 22, 120)     # progressive disease
), 1)

wf <- data.frame(
  patient     = paste0("P", sprintf("%02d", seq_len(n))),
  best_change = best_change,
  response    = response
)

head(wf)
  patient best_change response
1     P01        -5.9       SD
2     P02       -19.3       SD
3     P03       -78.5       PR
4     P04       -89.7       PR
5     P05        -6.9       SD
6     P06       -90.6       PR

We also simulate the longitudinal trajectories for the companion spider plot: a straight-line drift from baseline to the best change with small week-to-week noise, with progressors accelerating late.

set.seed(2027)
weeks <- seq(0, 48, 6)

spider <- do.call(rbind, lapply(seq_len(nrow(wf)), function(i) {
  k <- length(weeks)
  endpoint <- wf$best_change[i]
  base <- approx(x = c(1, k), y = c(0, endpoint), xout = 1:k)$y
  noise <- runif(k, -4, 4)
  if (wf$response[i] == "PD") noise <- noise + seq(0, 12, length.out = k)  # acceleration
  data.frame(patient = wf$patient[i], week = weeks,
             change = round(pmin(base + noise, 130), 1),
             response = wf$response[i])
}))

head(spider)
  patient week change response
1     P01    0   -2.6       SD
2     P01    6   -1.5       SD
3     P01   12   -3.5       SD
4     P01   18   -0.6       SD
5     P01   24   -4.6       SD
6     P01   30   -5.2       SD

Visualization

1. Basic Waterfall Plot

Sort patients by best change and flip the coordinates so bars read like the classic publication layout.

p1 <- wf %>%
  mutate(patient = fct_reorder(patient, best_change)) %>%
  ggplot(aes(patient, best_change)) +
  geom_col(fill = "#4393C3", width = 0.75) +
  coord_flip() +
  labs(x = NULL, y = "Best % change from baseline") +
  theme_bw()
p1
Figureย 1: Basic waterfall plot of best tumor change per patient.

2. RECIST-Colored Waterfall with Threshold Lines

Color bars by response category and add the RECIST reference lines: โˆ’30% marks the partial-response boundary and +20% the progression boundary (formally, PD also requires an absolute increase of at least 5 mm).

recist_colors <- c(CR = "#1B7837", PR = "#66BD63", SD = "#FFB300", PD = "#C51B7D")

p2 <- wf %>%
  mutate(patient = fct_reorder(patient, best_change)) %>%
  ggplot(aes(patient, best_change, fill = response)) +
  geom_col(width = 0.75) +
  geom_hline(yintercept = c(-30, 20), linetype = "dashed", color = "grey35") +
  scale_fill_manual(values = recist_colors, name = "RECIST") +
  coord_flip() +
  labs(x = NULL, y = "Best % change from baseline") +
  theme_bw() +
  theme(legend.position = "top")
p2
Figureย 2: Waterfall plot colored by RECIST response with reference lines at -30% and +20%.

The two dashed lines instantly reveal the response rate (bars below โˆ’30%) versus the disease-control rate (all bars below +20%).

3. Companion Spider Plot

p3 <- spider %>%
  ggplot(aes(week, change, group = patient, color = response)) +
  geom_hline(yintercept = c(-30, 20), linetype = "dashed", color = "grey35") +
  geom_line(alpha = 0.75, linewidth = 0.6) +
  scale_color_manual(values = recist_colors, name = "RECIST") +
  labs(x = "Weeks on treatment", y = "% change from baseline") +
  theme_bw() +
  theme(legend.position = "top")
p3
Figureย 3: Spider plot of longitudinal tumor change; the waterfall shows endpoints, the spider shows trajectories.

4. Combined Figure

p2 + p3 + plot_annotation(
  title = "Best tumor response and its longitudinal trajectories",
  tag_levels = "A"
)
Figureย 4: Waterfall (left) and spider (right) plots combined with patchwork.

Reading them together: bars tell the depth of response, lines tell its shape โ€” early shrinkers, late progressors and primary refractory patients are distinguishable in the spider plot only.

Application

Waterfall plots are ubiquitous in clinical oncology papers and FDA/EMA filings to summarize anti-tumor activity of a regimen; the combined waterfall + spider panel below is the typical presentation.

WaterfallPlot Application

Reference

[1] Eisenhauer EA, Therasse P, Bogaerts J, et al.ย New response evaluation criteria in solid tumours: revised RECIST guideline (version 1.1). Eur J Cancer. 2009;45(2):228-247. doi:10.1016/j.ejca.2008.10.026

[2] Kim MS, Prasad V. Assessment of accuracy of waterfall plot representations of response rates in cancer treatment published in medical journals. JAMA Netw Open. 2019;2(5):e193981. doi:10.1001/jamanetworkopen.2019.3981