Experiment

library(tidyverse)
roi_df <- data.frame(event = c("investment", "return"),
                     change = c(-800, 1200))


compute_panel_waterfall <- function(data, scales, width = .90){
  
  data %>% 
  arrange(x) %>% 
  mutate(balance = cumsum(c(0, 
                            change[-nrow(.)]))) %>% 
  mutate(direction = factor(sign(change))) %>% 
  mutate(xmin = as.numeric(as.factor(x)) - width/2,
         xmax = as.numeric(as.factor(x)) + width/2,
         ymin = balance,
         ymax = balance + change) %>% 
  mutate(y = ymax) %>% 
  mutate(gain_loss = ifelse(direction == 1, "positive", "negative"))
  
}  
  
roi_df |>
  select(x = event, change) |>
  compute_panel_waterfall()
##            x change balance direction xmin xmax ymin ymax    y gain_loss
## 1 investment   -800       0        -1 0.55 1.45    0 -800 -800  negative
## 2     return   1200    -800         1 1.55 2.45 -800  400  400  positive

Using create layer temp outside of package development environment…

ggtemp:::create_layer_temp("geom_waterfall", 
                           compute_panel = compute_panel_waterfall,
                           required_aes = c("x", "change"), 
                           geom = "rect")

ggplot(roi_df) + 
  aes(x = event) +
  aes(change = change) + 
  geom_hline(yintercept = 0, alpha) +
  geom_waterfall() + 
  aes(fill = after_stat(gain_loss)) 
## Warning: `geom_hline()`: Ignoring `mapping` because `yintercept` was provided.

Next step, expand x axis for start balance and end balance… Less obvious than it seemed when I started.

Probably should try with numeric x first, and then look into factor level x.

Closing remarks, Other Relevant Work, Caveats