Search code examples
rggplot2geom-bar

How to create a waterfall plot?


I wanted to visualize the bar graph in a additive way (waterfall plot, see below).

This is the data:

structure(list(Parameter = c("Driving", "Driver Behaviour", "Road Quality", 
                             "Passenger load", "Speed", "Topography", "climate", "total"), 
               Values = c(0.8, 0.2, 0.2, 0.2, 0.24, 0.5, 0.8, 2.82)),
          row.names = c(NA, -8L), class = "data.frame")
#          Parameter Values
# 1          Driving   0.80
# 2 Driver Behaviour   0.20
# 3     Road Quality   0.20
# 4   Passenger load   0.20
# 5            Speed   0.24
# 6       Topography   0.50
# 7          climate   0.80
# 8            total   2.82

This is the output im trying to produce. Is there any way i can do it in R?

enter image description here


Solution

  • Still in need of some polishing but in principle your watefall chart can be achieved like so:

    BTW: Because of rounding errors your data gives a total of 2.94 instead of 2.82.

    d <- structure(list(Parameter = c("Driving", "Driver Behaviour", "Road Quality", 
                                 "Passenger load", "Speed", "Topography", "climate", "total"), 
                   Values = c(0.8, 0.2, 0.2, 0.2, 0.24, 0.5, 0.8, 2.82)),
              row.names = c(NA, -8L), class = "data.frame")
    
    library(ggplot2)
    library(dplyr)
    
    # Prepare the dataset
    d1 <- d %>%
      mutate(ymax = cumsum(Values),
             ymin = lag(ymax, default = 0),
             xmax = as.numeric(factor(Parameter, levels = Parameter)),
             xmin = lag(xmax, default = 0),
             x = (xmin + xmax) / 2, 
             y = (ymin + ymax) / 2,
             label = Values,
             label_color = "white",
             ) %>% 
      # Get the total right
      mutate(ymin = ifelse(Parameter == "total", 0, ymin),
             ymax = ifelse(Parameter == "total", Values, ymax),
             y = ifelse(Parameter %in% c("Driving", "total"), Values + .2, y),
             label = case_when(
               Parameter %in% c("Driving") ~ paste0("Best Case\n", Values),
               Parameter %in% c("total") ~ paste0("Worst Case\n", Values),
               TRUE ~ as.character(Values)),
             label_color = ifelse(Parameter %in% c("Driving", "total"), "black", "white"))
    
    ggplot(d1, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax)) +
      geom_rect(fill = "#E40019") +
      geom_text(aes(x = x, y = y, label = label, color = label_color), show.legend = FALSE) +
      scale_x_continuous(breaks = seq(.5, 7.5, 1), labels = d1$Parameter) +
      scale_color_manual(values = c(white = "white", black = "black")) +
      theme_bw()
    

    Created on 2020-06-16 by the reprex package (v0.3.0)