@@ -67,9 +67,19 @@ shinyApp(
67
67
choices = forecaster_options ,
68
68
multiple = TRUE
69
69
),
70
+ selectInput(" baseline" ,
71
+ " Baseline forecaster:" ,
72
+ choices = forecaster_options ,
73
+ multiple = FALSE
74
+ ),
75
+ checkboxInput(
76
+ " scale_by_baseline" ,
77
+ " Scale by baseline forecaster" ,
78
+ value = FALSE ,
79
+ ),
70
80
radioButtons(
71
81
" selected_metric" ,
72
- " Metric :" ,
82
+ " Error metric :" ,
73
83
c(
74
84
" Mean WIS" = " wis" ,
75
85
# "Mean WIS per 100k" = "wis_per_100k",
@@ -88,12 +98,10 @@ shinyApp(
88
98
choices = c(" forecaster" , " ahead" , " geo_value" ),
89
99
multiple = TRUE
90
100
),
91
- radioButtons(" facets_share_scale" ,
92
- " Share y scale between subplots:" ,
93
- c(
94
- " Yes" = " fixed" ,
95
- " No" = " free_y"
96
- )
101
+ checkboxInput(
102
+ " facets_share_scale" ,
103
+ " Share y scale between subplots" ,
104
+ value = TRUE ,
97
105
),
98
106
sliderInput(" selected_forecast_date_range" ,
99
107
" Forecast date range:" ,
@@ -125,9 +133,10 @@ shinyApp(
125
133
},
126
134
server = function (input , output , session ) {
127
135
filtered_scorecards_reactive <- reactive({
128
- if (length(input $ selected_forecasters ) == 0 ) { return (data.frame ()) }
136
+ agg_forecasters <- unique(c(input $ selected_forecasters , input $ baseline ))
137
+ if (length(agg_forecasters ) == 0 ) { return (data.frame ()) }
129
138
130
- processed_evaluations_internal <- lapply(input $ selected_forecasters , function (forecaster ) {
139
+ processed_evaluations_internal <- lapply(agg_forecasters , function (forecaster ) {
131
140
load_forecast_data(forecaster ) %>> %
132
141
filter(
133
142
.data $ forecast_date %>> % between(.env $ input $ selected_forecast_date_range [[1L ]], .env $ input $ selected_forecast_date_range [[2L ]]),
@@ -141,8 +150,35 @@ shinyApp(
141
150
input_df <- filtered_scorecards_reactive()
142
151
if (nrow(input_df ) == 0 ) { return () }
143
152
153
+ # Normalize by baseline scores. This is not relevant for coverage, which is compared
154
+ # to the nominal confidence level.
155
+ if (input $ scale_by_baseline && input $ selected_metric != " ic80" ) {
156
+ # These merge keys are overkill; this should be fully specified by
157
+ # c("forecast_date", "target_end_date", "geo_value")
158
+ merge_keys <- c(" forecast_date" , " target_end_date" , " ahead" , " issue" , " geo_value" )
159
+ # Load selected baseline
160
+ baseline_scores <- load_forecast_data(input $ baseline )[, c(merge_keys , input $ selected_metric )]
161
+
162
+ baseline_scores $ score_baseline <- baseline_scores [[input $ selected_metric ]]
163
+ baseline_scores [[input $ selected_metric ]] <- NULL
164
+
165
+ # Add on reference scores from baseline forecaster.
166
+ # Note that this drops any scores where there isn't a corresponding
167
+ # baseline value. If a forecaster and a baseline cover
168
+ # non-overlapping dates or use different aheads, the forecaster will
169
+ # not be shown.
170
+ input_df <- inner_join(
171
+ input_df , baseline_scores ,
172
+ by = merge_keys , suffix = c(" " , " " )
173
+ )
174
+ # Scale score by baseline forecaster
175
+ input_df [[input $ selected_metric ]] <- input_df [[input $ selected_metric ]] / input_df $ score_baseline
176
+ }
177
+
178
+
144
179
x_tick_angle <- list (tickangle = - 30 )
145
180
facet_x_tick_angles <- setNames(rep(list (x_tick_angle ), 10 ), paste0(" xaxis" , 1 : 10 ))
181
+ scale_type <- ifelse(input $ facets_share_scale , " fixed" , " free_y" )
146
182
147
183
input_df %>> %
148
184
# Aggregate scores over all geos
@@ -180,9 +216,9 @@ shinyApp(
180
216
`+`(if (length(input $ facet_vars ) == 0L ) {
181
217
theme()
182
218
} else if (length(input $ facet_vars ) == 1L ) {
183
- facet_wrap(input $ facet_vars , scales = input $ facets_share_scale )
219
+ facet_wrap(input $ facet_vars , scales = scale_type )
184
220
} else {
185
- facet_grid(as.formula(paste0(input $ facet_vars [[1L ]], " ~ " , paste(collapse = " + " , input $ facet_vars [- 1L ]))), scales = input $ facets_share_scale )
221
+ facet_grid(as.formula(paste0(input $ facet_vars [[1L ]], " ~ " , paste(collapse = " + " , input $ facet_vars [- 1L ]))), scales = scale_type )
186
222
}) %>> %
187
223
ggplotly() %>> %
188
224
{inject(layout(. , hovermode = " x unified" , legend = list (orientation = " h" , title = list (text = " forecaster" )), xaxis = x_tick_angle , !!! facet_x_tick_angles ))}
0 commit comments