Skip to content

Commit 7176d82

Browse files
Separate plotting code from data prep
1 parent 0cda0d0 commit 7176d82

2 files changed

Lines changed: 347 additions & 137 deletions

File tree

‎R/plotting.R‎

Lines changed: 100 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# TODO: add documentations for these functions
21
#' Plotting theme for vimcheck
32
#'
43
#' @description
@@ -17,6 +16,8 @@
1716
#'
1817
#' @return A `ggplot2` theme that can be added to `ggplot2` plots or objects.
1918
#'
19+
#' @keywords plotting
20+
#'
2021
#' @export
2122
theme_vimc <- function(x_text_angle = 45, y_text_angle = 0, ...) {
2223
ggplot2::theme_bw() +
@@ -44,45 +45,36 @@ theme_vimc <- function(x_text_angle = 45, y_text_angle = 0, ...) {
4445
#' Plotting functions for burden and impact diagnostics. This documentation
4546
#' holds all plotting functions for now.
4647
#'
47-
#' @param d
48+
#' @param data A `<data.frame>` that gives the comparison between VIMC-provided
49+
#' and modeller-used demography values, in long-format. This is primarily
50+
#' expected to be the output of `check_demography_alignment()` processed by
51+
#' `prep_plot_demography()`.
4852
#'
49-
#' @param fig_number
53+
#' @param fig_number The figure number.
5054
#'
5155
#' @return A `<ggplot>` object that can be printed to screen in the plot frame
5256
#' or saved to an output device (i.e., saved as an image file).
5357
#'
54-
#' @examples
58+
#' @keywords plotting
5559
#'
5660
#' @export
57-
plot_compare_demography <- function(d, fig_number) {
58-
num_countries <- length(unique(d$country))
59-
names_melting_data <- c(
60-
"scenario",
61-
"age",
62-
"year",
63-
"expected",
64-
"provided",
65-
"difference"
66-
)
67-
names_melting_by <- c("scenario", "age", "year")
68-
69-
# TODO: use tidyr; BIG PICTURE: NO DATA PREP IN PLOTTING FUNCTIONS!
70-
tot <- reshape2::melt(d[, names_melting_data], id.vars = names_melting_by)
71-
dat <- tot %>%
72-
dplyr::group_by(variable, scenario, year, age) %>%
73-
dplyr::summarise(value = sum(value)) %>%
74-
dplyr::mutate(millions = value / 1e6) %>%
75-
dplyr::arrange(age)
61+
plot_compare_demography <- function(data, fig_number) {
62+
# NOTE: not implementing a lot of checks on inputs
63+
checkmate::assert_tibble(data)
64+
checkmate::assert_count(fig_number, positive = TRUE) # no zeros allowed
7665

7766
# TODO: use .data and .vars, import or namespace functions
78-
g <- ggplot(data = dat, aes(x = year, y = millions, fill = age)) +
79-
geom_bar(stat = "identity") +
67+
g <- ggplot(
68+
data = data,
69+
aes(x = year, y = millions, fill = age)
70+
) +
71+
geom_col() +
8072
facet_wrap(~ scenario + variable, ncol = 3) +
8173
scale_fill_distiller(palette = "PuOr") +
82-
geom_hline(yintercept = 0, color = 'red') +
74+
geom_hline(yintercept = 0, colour = "red") +
8375
labs(
8476
x = "calendar year",
85-
y = glue::glue("people (in millions"),
77+
y = "people (in millions",
8678
title = glue::glue(
8779
"Fig. {fig_number}. Comparison between interpolated population and \\
8880
cohort size ({num_countries} countries)."
@@ -95,23 +87,24 @@ plot_compare_demography <- function(d, fig_number) {
9587

9688
#' @name plotting
9789
#'
98-
#' @param burden
90+
#' @param burden_age A `<tibble>` with the minimum column names
91+
#' "age", "millions"
9992
#'
10093
#' @export
101-
plot_age_patterns <- function(burden, fig_number) {
102-
# TODO: REMOVE DATA PREP FROM PLOTTING FNS
103-
d <- burden %>%
104-
group_by(scenario, burden_outcome, age) %>%
105-
summarise(millions = sum(value) / 1e6)
94+
plot_age_patterns <- function(burden_age, fig_number) {
95+
checkmate::assert_tibble(burden_age)
96+
checkmate::assert_count(fig_number, positive = TRUE) # no zeros allowed
10697

107-
g <- ggplot(d, aes(x = age, y = millions)) +
108-
geom_bar(stat = "identity") +
98+
max_age <- max(burden_age$age) + 1
99+
100+
g <- ggplot(burden_age, aes(x = age, y = value_millions)) +
101+
geom_col() +
109102
facet_grid(
110103
burden_outcome ~ scenario,
111104
scales = "free_y",
112105
labeller = labeller(scenario = label_wrap_gen(10))
113106
) +
114-
coord_cartesian(xlim = c(0, max(d$age) + 1)) +
107+
coord_cartesian(xlim = c(NA_real_, max_age)) + # no lower limit, expect > 0
115108
labs(
116109
y = "people (in millions)",
117110
title = glue::glue(
@@ -125,29 +118,16 @@ plot_age_patterns <- function(burden, fig_number) {
125118

126119
#' @name plotting
127120
#'
128-
#' @param year_max
121+
#' @param burden_decades A `<tibble>` giving the burden by decade, up to
122+
#' `year_max`. This should be the output of [prep_plot_burden_decades()].
129123
#'
130124
#' @export
131-
plot_global_burden_decades <- function(burden, year_max, fig_number) {
132-
# TODO: prefer moving these conditional checks elsewhere
133-
# TODO: prefer moving data prep outside plotting fn
134-
stopifnot(year_max %% 10 == 0)
135-
d <- burden %>%
136-
filter(year <= year_max) %>%
137-
mutate(year2 = ifelse(year == year_max, year_max - 1, year)) %>%
138-
mutate(decade = floor(year2 / 10) * 10) %>%
139-
mutate(
140-
decade_label = ifelse(
141-
decade == year_max - 10,
142-
paste0(decade, "-", decade + 10),
143-
paste0(decade, "-", decade + 9)
144-
)
145-
) %>%
146-
group_by(scenario, burden_outcome, decade_label) %>%
147-
summarise(millions = sum(value) / 1e6)
148-
149-
g <- ggplot(d, aes(x = scenario, y = millions, fill = scenario)) +
150-
geom_bar(stat = "identity") +
125+
plot_global_burden_decades <- function(burden_decades, fig_number) {
126+
g <- ggplot(
127+
burden_decades,
128+
aes(x = scenario, y = millions, fill = scenario)
129+
) +
130+
geom_col() +
151131
facet_grid(burden_outcome ~ decade_label, scales = "free_y") +
152132
labs(
153133
y = "people (in millions)",
@@ -169,33 +149,38 @@ plot_global_burden_decades <- function(burden, year_max, fig_number) {
169149

170150
#' @name plotting
171151
#'
172-
#' @param d
173-
#'
174-
#' @param outcome
152+
#' @param burden_data This is expected to be a `<tibble>` from a
153+
#' nested-`<tibble>` constructed using [prep_plot_global_burden()].
175154
#'
176155
#' @export
177-
plot_global_burden <- function(d, outcome, fig_number) {
178-
data_ <- dplyr::filter(
179-
d,
180-
.data$burden_outcome == outcome
156+
plot_global_burden <- function(burden_data, outcome_name, fig_number) {
157+
checkmate::assert_tibble(burden_data)
158+
checkmate::assert_subset(
159+
outcome_name,
160+
burden_outcome_names
181161
)
162+
checkmate::assert_count(fig_number)
163+
164+
scenarios_per_gridcol <- 10
182165

183166
g <- ggplot(
184-
data,
185-
aes(x = year, y = millions, fill = age)
167+
burden_data,
168+
aes(year, millions, fill = age)
186169
) +
187-
geom_bar(stat = "identity", aes(fill = age)) +
170+
geom_col() +
188171
facet_grid(
189172
~scenario,
190173
scales = "free_y",
191-
labeller = labeller(scenario = label_wrap_gen(10)) # TODO: avoid magic numbers
174+
labeller = labeller(
175+
scenario = label_wrap_gen(scenarios_per_gridcol)
176+
)
192177
) +
193178
scale_fill_distiller(palette = "Spectral") +
194179
labs(
195180
x = "calendar year",
196-
y = paste(outcomes_list[i], "(in millions)"), # TODO: where is outcomes_list!?
181+
y = glue::glue("{outcome_name} (in millions)"),
197182
title = glue::glue(
198-
"Fig. {fig_number}: Global trends of disease burden ({outcome})."
183+
"Fig. {fig_number}: Global trends of disease burden ({outcome_name})."
199184
)
200185
) +
201186
theme_vimc(x_text_angle = 90)
@@ -205,43 +190,43 @@ plot_global_burden <- function(d, outcome, fig_number) {
205190

206191
#' @name plotting
207192
#'
208-
#' @param cov
193+
#' @param coverage_set A `<tibble>` that is the output of
194+
#' [prep_plot_coverage_set()].
209195
#'
210196
#' @export
211-
plot_coverage_set <- function(cov, figure_number) {
212-
# TODO: remove data prep
213-
no_vacc <- expand_grid(
214-
year = unique(cov$year),
215-
country = unique(cov$country)
216-
) %>%
217-
mutate(
218-
coverage = 0,
219-
delivery = "none",
220-
scenario_description = "No vaccination"
221-
)
197+
plot_coverage_set <- function(coverage_set, figure_number) {
198+
checkmate::assert_tibble(coverage_set)
199+
checkmate::assert_count(figure_number)
200+
201+
dodge_width <- 0.9
202+
col_opacity <- 0.7
203+
scenarios_per_gridcol <- 10
222204

223-
cov1 <- cov %>%
224-
mutate(delivery = paste(vaccine, activity_type, sep = "-")) %>%
225-
select(scenario_description, delivery, country, year, coverage) %>%
226-
bind_rows(no_vacc)
205+
disease_name <- unique(coverage_set$disease) # expecting a single value
227206

228-
g <- ggplot(cov1, aes(x = year, y = coverage, fill = delivery)) +
229-
geom_bar(
230-
stat = "identity",
231-
position = position_dodge(width = 0.9),
232-
alpha = 0.7
207+
g <- ggplot(
208+
coverage_set,
209+
aes(x = year, y = coverage, fill = delivery)
210+
) +
211+
geom_col(
212+
# TODO: check if dodging is really needed
213+
position = position_dodge(dodge_width),
214+
alpha = col_opacity
233215
) +
234216
facet_grid(
235-
"country ~ scenario_description",
217+
rows = vars(country),
218+
cols = vars(scenario_description),
236219
scales = "free_y",
237-
labeller = labeller(scenario_description = label_wrap_gen(10))
220+
labeller = labeller(
221+
scenario_description = label_wrap_gen(scenarios_per_gridcol)
222+
)
238223
) +
239-
scale_x_continuous(breaks = pretty(unique(cov1$year))) +
224+
scale_x_continuous() +
240225
labs(
241226
x = "calendar year",
242227
y = "Proportion of target population",
243228
title = glue::glue(
244-
"Fig. {figure_number}: Coverage sets for {cov$disease[1]}"
229+
"Fig. {figure_number}: Coverage sets for {disease_name}"
245230
)
246231
) +
247232
theme_vimc(90)
@@ -251,63 +236,41 @@ plot_coverage_set <- function(cov, figure_number) {
251236

252237
#' @name plotting
253238
#'
254-
#' @param fvp
255-
#'
256-
#' @param year_min
257-
#'
258-
#' @param year_max
239+
#' @param fvp_data A `<tibble>` of estimates of fully-vaccinated persons (FVPs) per
240+
#' scenario, with scenarios as factors in order of the number of adjusted-FVPs.
241+
#' Expected to be the output of [prep_plot_fvp()].
259242
#'
260243
#' @export
261-
plot_fvp <- function(fvp, year_min, year_max, figure_number) {
262-
# TODO: PREFER TO REMOVE DATA PREP CODE
263-
no_vacc <- expand_grid(
264-
year = unique(fvp$year),
265-
country = unique(fvp$country)
266-
) %>%
267-
mutate(fvps_adjusted = 0, scenario_description = "No vaccination")
268-
269-
fvp_final <- bind_rows(fvp, no_vacc) %>%
270-
filter(year >= year_min & year <= year_max) %>%
271-
mutate(scenario = as.factor(scenario_description))
244+
plot_fvp <- function(fvp_data, figure_number) {
245+
checkmate::assert_tibble(fvp_data)
246+
checkmate::assert_count(figure_number)
272247

273-
fvp_final$scenario <- relevel(fvp_final$scenario, "No vaccination")
274-
fvp_final$scenario <- gsub(tolower(fvp$disease[1L]), "", fvp_final$scenario)
275-
fvp_final$scenario <- gsub("-", " ", fvp_final$scenario)
248+
scenarios_per_gridcol <- 10
249+
scale_millions <- 1e-6
250+
disease_name <- unique(fvp_data$disease)
276251

277-
scenario_order <- c(names(sort(tapply(
278-
fvp_final$fvps_adjusted,
279-
fvp_final$scenario,
280-
sum,
281-
na.rm = TRUE
282-
))))
283-
284-
fvp_final$scenario <- forcats::fct_relevel(fvp_final$scenario, scenario_order)
285-
286-
fvp_agg <-
287-
fvp_final %>%
288-
dplyr::group_by(year, scenario, disease) %>%
289-
dplyr::summarise(fvp = sum(fvps_adjusted, na.rm = TRUE))
290-
291-
# TODO: prefer to use a scale transform rather than touching data
292-
g <- ggplot(fvp_agg, aes(x = year, y = fvp / 1e6, fill = scenario)) +
293-
geom_bar(
294-
stat = "identity",
295-
colour = "midnightblue",
252+
g <- ggplot(
253+
fvp_data,
254+
aes(x = year, y = fvp, fill = scenario)
255+
) +
256+
geom_col(
296257
fill = "midnightblue"
297258
) +
298259
facet_grid(
299260
~scenario,
300261
scales = "free_y",
301-
labeller = labeller(scenario = label_wrap_gen(10))
262+
labeller = labeller(scenario = label_wrap_gen(scenarios_per_gridcol))
263+
) +
264+
scale_x_continuous() +
265+
scale_y_continuous(
266+
labels = scales::label_number(scale = scale_millions)
302267
) +
303-
scale_x_continuous(breaks = pretty(unique(fvp_agg$year))) +
304-
ylab(paste("FVP (in millions)")) +
305268
labs(
306269
x = "calendar year",
307270
y = "FVP (in millions)",
308271
title = glue::glue(
309272
"Fig. {figure_number}: Fully Vaccinated Persons at global level by \\
310-
scenario for {fvp$disease[1L]}"
273+
scenario for {disease_name}"
311274
)
312275
) +
313276
theme_vimc(90, legend.position = "none")

0 commit comments

Comments
 (0)