-
Notifications
You must be signed in to change notification settings - Fork 2
/
ggtornado.R
100 lines (92 loc) · 3.39 KB
/
ggtornado.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#' Create a "tornado" plot using ggplot2
#'
#' This function creates a "tornado" plot using the ggplot2 package. These
#' are primarily used to display results of a sensitivity analysis.
#' @param data A data frame containing the results of a sensitivity analysis.
#' @param baseline The baseline value for the sensitivity analysis.
#' @param var The data column identifying the variable name being varied.
#' @param level The data column identifying the sensitivity case level
#' (usually 'high' or 'low', relative to the baseline).
#' @param value The data column identifying the value of the variable being
#' varied.
#' @param result The data column identifying the result when the variable 'var'
#' is set at the value of 'value'.
#' @importFrom ggplot2 ggplot aes geom_col geom_text scale_x_continuous
#' labs theme theme_bw
#' @importFrom rlang .data
#' @export
#' @examples
#'
#' # Create an example data frame of a sensitivity analysis - columns:
#' # 'var' <- The name of the variable being varied.
#' # 'level' <- 'high' or 'low' (relative to the baseline).
#' # 'value' <- The value of the variable being varied.
#' # 'result' <- The result of the output value at the varied variable value.
#' data <- data.frame(
#' var = c('price', 'price', 'fuelEconomy', 'fuelEconomy',
#' 'accelTime', 'accelTime'),
#' level = rep(c('high', 'low'), 3),
#' value = c(10, 20, 25, 15, 10, 6),
#' result = c(0.95, 0.15, 0.90, 0.60, 0.85, 0.75)
#' )
#'
#' # Make a tornado plot of the sensitivity analysis results:
#' library(ggplot2)
#'
#' ggtornado(
#' data = data,
#' baseline = 0.8, # Baseline result
#' var = 'var',
#' level = 'level',
#' value = 'value',
#' result = 'result'
#' )
#'
ggtornado <- function(
data,
baseline,
var,
level,
value,
result
) {
# Create a new data frame for plotting
df <- data[c(var, level, value, result)]
colnames(df) <- c('var', 'level', 'value', 'result')
# Add hust based on the level
df$hjust <- rep(c(0, 1), nrow(df) / 2)
# "Center" the result around the baseline result (so baseline is at 0)
df$result <- df$result - baseline
# Compute the range in change from low to high levels for sorting
df$resultRange <- stats::ave(abs(df$result), df$var, FUN = sum)
# dplyr solution
# df <- df %>%
# # "Center" the result around the baseline result (so baseline is at 0)
# mutate(result = result - baseline) %>%
# # Compute the range in change from low to high levels for sorting
# group_by(var) %>%
# mutate(resultRange = sum(abs(result)))
# Compute labels for the x-axis
lb <- floor(10*min(df$result))/10
ub <- ceiling(10*max(df$result))/10
breaks <- seq(lb, ub, (ub - lb) / 5)
breakLabs <- round(breaks + baseline, 2)
# Make the tornado diagram
plot <- ggplot(df,
aes(
x = .data$result,
y = stats::reorder(.data$var, .data$resultRange),
fill = level)
) +
geom_col(width = 0.6) +
# Add labels on bars
geom_text(aes(label = .data$value, hjust = .data$hjust), vjust = 0.5) +
scale_x_continuous(
limits = c(lb, ub),
breaks = breaks,
labels = breakLabs) +
labs(x = 'Result', y = 'Parameter') +
theme_bw() +
theme(legend.position = 'none') # Remove legend
return(plot)
}