/
plot_spiechart.R
202 lines (180 loc) · 7.49 KB
/
plot_spiechart.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#' Create score-based spie chart
#'
#' \code{plot_spiechart} generates for each indicator in the scoring
#' tibble a ggplot2-based spie chart to visualize the scores of each
#' criterion.
#'
#' @param summary_tbl The output tibble from the
#' \code{\link{summary_sc}} function.
#' @param col_press_type Colors for the spie chart slices representing
#' criteria 9 (sensitivity; opaque) and 9 (robustness; transparent).
#'
#' The colors distinguish the different pressure types. The default
#' is set to the RColourBrewer palette "Set1".
#' @param col_crit8_11 Colors for the spie chart slices representing
#' criteria 8 (trend) and 11 (management application). The default is
#' set to cyan1 and yellow2.
#' @param lab_size Size for the labels naming the significant pressures. The default is 6.
#' @param title_size Size for the title naming the indicator. The default is 8.
#'
#' @details
#' The overall performance of each tested IND is illustrated using a spie chart,
#' which has been shown to be a well-suited graphical tool for
#' displaying multivariate data in comparative indicator evaluations
#' (Stafoggia \emph{et al.}, 2011). A spie chart superimposes a normal pie chart with
#' a modified polar area chart to permit the comparison of two sets of related
#' data, e.g. the maximum achievable scores and each IND’s realized scores. In this
#' function, the slice width is kept constant, while the length of the slices
#' represents the percentage of scores achieved, with the boundary line (i.e. the
#' inner gray circle) indicating the full 100%.
#'
#' The two unlabeled slices at the top represent the trend (right) and management
#' (left) criteria. The sensitivity and robustness scores are shown individually for
#' each pressure where a significant relationship was found. These are the labeled
#' slices grouped by their pressure type represented by dotted division lines and the
#' segmented outer gray circle as well as pressure type-specific colors (sensitivity
#' scores are displayed in opaque color, robustness scores in transparent color).
#'
#' The plot slices adjust to the number of criteria used for the scoring function
#' (that are present in crit_scores_tmpl).
#'
#' @return The function returns a list of \code{\link[ggplot2]{ggplot}} objects.
#'
#' @references
#' Stafoggia, M., Lallo, A., Fusco, D., Barone, A.P., D`Ovidio, M., Sorge, C.,
#' Perucci, C.A. (2011) Spie charts, target plots, and radar plots for
#' displaying comparative outcomes of health care. \emph{Journal of Clinical
#' Epidemiology} 64, 770-778.
#'
#' @family score-based IND performance functions
#'
#' @export
#'
#' @examples
#' # Using the Baltic Sea demo data in this package
#' scores_tbl <- scoring(trend_tbl = model_trend_ex,
#' mod_tbl = all_results_ex, press_type = press_type_ex)
#' summary_tbl <- summary_sc(scores_tbl)
#' p <- plot_spiechart(summary_tbl)
#' p$TZA
#'
#' \donttest{
#' # Show all spiecharts together
#' gridExtra::grid.arrange(grobs = p)
#'
#' # To modify the plot
#' p <- plot_spiechart(summary_tbl, col_crit8_11 = c("black",
#' "thistle4"), col_press_type = RColorBrewer::brewer.pal(3,
#' name = "Accent"), lab_size = 4, title_size = 4)
#' gridExtra::grid.arrange(grobs = p)
#'
#' # Remove pressure-independent criteria for the plot (e.g.
#' # management) (easiest in the score tibble)
#' scores_tbl$C11 <- NULL
#' summary_tbl <- summary_sc(scores_tbl)
#' p <- plot_spiechart(summary_tbl)
#' gridExtra::grid.arrange(grobs = p)
#'
#' # Exclude additionally one pressure-specific criterion
#' # (e.g. sensitivity C9) (easiest by removing columns
#' # in the first list of the summary)
#' summary_tbl[[1]] <- summary_tbl[[1]][ ,
#' ! names(summary_tbl[[1]]) %in% c("C9", "C9_in%")]
#' p <- plot_spiechart(summary_tbl)
#' gridExtra::grid.arrange(grobs = p)
#' }
plot_spiechart <- function(summary_tbl, col_press_type = NULL,
col_crit8_11 = NULL, lab_size = 6, title_size = 8) {
# Data input validation -----------------------
if (missing(summary_tbl)) {
stop("Argument summary_tbl is missing.")
}
# Check input list
if (class(summary_tbl) != "list") {
stop("summary_tbl has to be a list (output of summary_sc() function)!")
}
# Data re-organization ----------------------------
# Check if crit 8 and 11 were scored (pressure
# independent categories)
n_c8_c11 <- c(any(grepl("C8_in%", names(summary_tbl[[1]])) ==
TRUE), any(grepl("C11_in%", names(summary_tbl[[1]])) ==
TRUE))
# Check if crit 9 and 10 were scored (pressure-spec
# categories)
n_c9_c10 <- c(any(grepl("C9_in%", names(summary_tbl[[1]])) ==
TRUE), any(grepl("C10_in%", names(summary_tbl[[1]])) ==
TRUE))
# Order pressure-specific summary by ind,
# press_type and then press
summary_tbl[[2]] <- summary_tbl[[2]] %>%
dplyr::arrange(!!!rlang::syms(c("ind",
"press_type", "press")))
# Split summary_tbl by indicators
split_input <- purrr::map(summary_tbl[[1]]$ind,
~summary_tbl[[2]][summary_tbl[[2]]$ind == .,
])
# Get all press_types
press_type <- unique(summary_tbl[[2]]$press_type)[!is.na(unique(summary_tbl[[2]]$press_type))] %>%
sort()
# Get categories and subcategories for scaling
cat <- data.frame(press_type = press_type, n = 0,
stringsAsFactors = FALSE)
# Calculate n as max possible count of pressures in
# one category
for (i in seq_along(press_type)) {
cat$n[i] <- max(purrr::map_dbl(split_input,
~length(.x$press_type[.x$press_type ==
press_type[i]])))
}
# Get maximum number of possible pressures
total_n <- sum(cat$n, na.rm = TRUE) * sum(n_c9_c10)
# Add n max for each press_type
split_input <- suppressMessages(purrr::map(split_input,
~dplyr::left_join(., cat, by = "press_type")))
# Add count of sign. pressures/press_type
for (i in 1:length(split_input)) {
if (!is.na(split_input[[i]]$press_type[1])) {
split_input[[i]]$n_press <- purrr::map_dbl(split_input[[i]]$press_type,
~length(which(split_input[[i]]$press_typ ==
.)))
}
}
# Plot-specific information ----------------------
# Get colours for each pressure_type
if (is.null(col_press_type))
suppressWarnings(col_press_type <- RColorBrewer::brewer.pal(length(press_type),
name = "Set1"))
if (is.null(col_crit8_11)) {
col_crit8_11 <- c("cyan1", "yellow2")
}
col_press <- data.frame(press_type = press_type,
col = col_press_type[1:length(press_type)],
stringsAsFactors = FALSE)
split_input <- suppressMessages(purrr::map(split_input,
~dplyr::left_join(., col_press)))
# Get scales for each slice
parting <- 360/(total_n + sum(n_c8_c11))
x <- 360/parting
# Assign borders for each slice
scale <- seq(from = 0, to = 360 - parting, length.out = x) +
parting/2
names(scale) <- 1:length(scale)
# Background for the plot
ground <- data.frame(x = c(0, 0, 360, 360), y1 = c(0,
110, 110, 0))
# Create borders for outer ring1
x_ring1 <- c(0, 360, 360, 0)
# Plot -----------------------------------------
theme_infog <- ggplot2::theme_classic() + ggplot2::theme(axis.line = ggplot2::element_blank(),
axis.title = ggplot2::element_blank(), axis.ticks = ggplot2::element_blank(),
axis.text.y = ggplot2::element_blank(), axis.text.x = ggplot2::element_blank())
p <- purrr::map2(split_input, summary_tbl[[1]]$ind,
~ plot_spie(split_input = .x, scale, parting, cat, summary_tbl[[1]],
ground, n_c8_c11, n_c9_c10, col_crit8_11,
x_ring1, theme_infog, ind = .y, lab_size = lab_size,
title_size = title_size))
# Give sublists names
names(p) <- summary_tbl$overview$ind
### END OF FUNCTION ###
return(p)
}