Skip to content

Commit 1fbae27

Browse files
authored
Merge pull request #141 from epiforecasts/model-classification
Better report model classification
2 parents a5cd7a8 + 04b697c commit 1fbae27

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

R/process-data.R

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,32 @@ source(here("R", "utils-variants.R"))
88

99
# Metadata ----------------------------------------------------------------
1010
# Get classification of model types
11-
classify_models <- function(file = here("data", "model-classification.csv")) {
11+
classify_models <- function(file = here("data", "model-classification.csv"),
12+
return_majority = TRUE) {
1213
methods <- read_csv(file) |>
1314
pivot_longer(
1415
-model,
1516
names_to = "classifier", values_to = "classification"
1617
) |>
1718
filter(!(is.na(classification) | classification == "#N/A")) |>
1819
group_by(model) |>
19-
summarise(
20-
agreement = (n_distinct(classification) == 1),
21-
classification = names(
22-
sort(table(classification), decreasing = TRUE)[1]
23-
),
24-
.groups = "drop"
25-
) |>
26-
mutate(classification = factor(
27-
classification,
28-
levels = c(
29-
"Agent-based", "Mechanistic",
30-
"Semi-mechanistic", "Statistical",
31-
"Machine learning", "Other"
32-
)
33-
))
20+
mutate(raters = n()) |>
21+
group_by(model, classification) |>
22+
mutate(votes = n(),
23+
agreement = votes == raters)
24+
25+
if (return_majority) {
26+
methods <- methods |>
27+
group_by(model) |>
28+
slice_max(order_by = votes, with_ties = FALSE)
29+
}
30+
31+
methods <- methods |>
32+
mutate(classification = ifelse(grepl("EpiExpert", model), "Judgement",
33+
classification),
34+
classification = factor(classification)) |>
35+
ungroup()
36+
3437
return(methods)
3538
}
3639

report/results.Rmd

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,16 @@ print_table1(scores)
6464
structures <- scores |>
6565
select(Model, Method, agreement) |>
6666
distinct()
67-
68-
structure_count <- table(structures$Method)
69-
structure_count <- structure_count[structure_count > 0]
67+
structure_count <- structures |>
68+
group_by(Method) |>
69+
summarise(agreement = sum(agreement),
70+
n = n(),
71+
p = agreement / n)
7072
```
7173

72-
We categorised `r structure_count[["Statistical"]]` models as statistical, `r structure_count[["Semi-mechanistic"]]` as semi-mechanistic, `r structure_count[["Mechanistic"]]` as mechanistic, `r structure_count[["Agent-based"]]` as agent-based and `r structure_count[["Other"]]` models that used human judgement forecasting as "other" (Supplementary Table). For `r sum(!structures$agreement)` (`r round(sum(!structures$agreement) / nrow(structures) * 100)`%) models, investigators disagreed on model classification. The majority of 2/3 was used as the final classification, with additional manual review which in all cases retained the majority decision. In the volume of forecasts provided, mechanistic, semi-mechanistic, and statistical models each contributed similar numbers of forecasts with approximately one-third each. Agent-based and "other" models provided fewer forecasts, representing only 1-2% of forecasts.
74+
Among 47 models, we categorised 17 models as using mechanistic structure, 12 as statistical, 12 as semi-mechanistic, 3 as agent-based and 3 that used human judgement forecasting (Supplementary Table). Raters disagreed on 17 (36%) model classifications. The majority of 2/3 was used as the final classification, with additional manual review which in all cases retained the majority decision. Raters most often disagreed when classifying semi-mechanistic models, with 8 out of 12 receiving one or more votes for a statistical model structure.
75+
76+
In the volume of forecasts provided, mechanistic, semi-mechanistic, and statistical models each contributed similar numbers of forecasts with approximately one-third each. Agent-based and judgement models provided fewer forecasts, representing only 1-2% of forecasts.
7377

7478
```{r target-description}
7579
targets <- scores |>

report/supplement/Supplement.Rmd

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@ table_metadata(scores) |>
7878
kable(caption = "Model characteristics contributing to the European COVID-19 Forecast Hub, by method used, number of countries targeted, and number of forecasts contributed.")
7979
```
8080

81+
```{r classification}
82+
model_classifier <- classify_models(return_majority = FALSE) |>
83+
distinct(model, classification, raters, votes, agreement) |>
84+
group_by(model) |>
85+
mutate(final = classification[which.max(votes)]) |>
86+
pivot_wider(names_from = classification, values_from = votes, values_fill = 0) |>
87+
filter(model %in% unique(scores$Model)) |>
88+
select(Model = model, `Final classification` = final,
89+
Agreement = agreement, `Total raters` = raters, everything()) |>
90+
arrange(Agreement, Model)
91+
92+
model_classifier |>
93+
kable(caption = "Classification of models by number of raters in total and agreement on model structure")
94+
```
95+
8196
\newpage
8297

8398
# Statistical methods

0 commit comments

Comments
 (0)