@@ -12,7 +12,10 @@ export RMSEVariable,
12
12
setindex!,
13
13
add_category,
14
14
add_model,
15
- add_unit!
15
+ add_unit!,
16
+ find_best_single_model,
17
+ find_worst_single_model,
18
+ median
16
19
17
20
"""
18
21
Holding root mean squared errors over multiple categories and models for a single
@@ -518,4 +521,75 @@ function add_unit!(rmse_var::RMSEVariable, model_name2unit::Dict)
518
521
return nothing
519
522
end
520
523
524
+ """
525
+ _unit_check(rmse_var::RMSEVariable)
526
+
527
+ Return nothing if units are not missing and units are the same across all models. Otherwise,
528
+ return an error.
529
+ """
530
+ function _unit_check (rmse_var:: RMSEVariable )
531
+ units = values (rmse_var. units) |> collect
532
+ unit_equal = all (unit -> unit == first (units), units)
533
+ (! unit_equal || first (units) == " " ) &&
534
+ error (" Units are not the same across all models or units are missing" )
535
+ return nothing
536
+ end
537
+
538
+ """
539
+ find_best_single_model(rmse_var::RMSEVariable; category_name = "ANN")
540
+
541
+ Return a tuple of the best single model and the name of the model. Find the best single
542
+ model using the root mean squared errors of the category `category_name`.
543
+ """
544
+ function find_best_single_model (rmse_var:: RMSEVariable ; category_name = " ANN" )
545
+ _unit_check (rmse_var)
546
+ categ_names = category_names (rmse_var)
547
+ ann_idx = categ_names |> (x -> findfirst (y -> (y == category_name), x))
548
+ isnothing (ann_idx) &&
549
+ error (" The category $category_name does not exist in $categ_names " )
550
+ rmse_vec = rmse_var[:, ann_idx] |> copy
551
+ # Replace all NaN with Inf so that we do not get NaN as a result
552
+ # We do this instead of filtering because if we filter, then we need to keep track of
553
+ # original indices
554
+ replace! (rmse_vec, NaN => Inf )
555
+ _, model_idx = findmin (rmse_vec)
556
+ mdl_names = model_names (rmse_var)
557
+ return rmse_var[model_idx, :], mdl_names[model_idx]
558
+ end
559
+
560
+ """
561
+ find_worst_single_model(rmse_var::RMSEVariable; category_name = "ANN")
562
+
563
+ Return a tuple of the worst single model and the name of the model. Find the worst single
564
+ model using the root mean squared errors of the category `category_name`.
565
+ """
566
+ function find_worst_single_model (rmse_var:: RMSEVariable ; category_name = " ANN" )
567
+ _unit_check (rmse_var)
568
+ categ_names = category_names (rmse_var)
569
+ ann_idx = categ_names |> (x -> findfirst (y -> (y == category_name), x))
570
+ isnothing (ann_idx) && error (" Annual does not exist in $categ_names " )
571
+ rmse_vec = rmse_var[:, ann_idx] |> copy
572
+ # Replace all NaN with Inf so that we do not get NaN as a result
573
+ # We do this instead of filtering because if we filter, then we need to keep track of
574
+ # original indices
575
+ replace! (rmse_vec, NaN => - Inf )
576
+ _, model_idx = findmax (rmse_vec)
577
+ mdl_names = model_names (rmse_var)
578
+ return rmse_var[model_idx, :], mdl_names[model_idx]
579
+ end
580
+
581
+ """
582
+ median(rmse_var::RMSEVariable)
583
+
584
+ Find the median using the root mean squared errors across all categories.
585
+
586
+ Any `NaN` is ignored in computing the median.
587
+ """
588
+ function median (rmse_var:: RMSEVariable )
589
+ _unit_check (rmse_var)
590
+ # Drop dimension so that size is (n,) instead of (1,n) so that it is consistent with the
591
+ # size of the arrays returned from find_worst_single_model and find_best_single_model
592
+ return dropdims (nanmedian (rmse_var. RMSEs, dims = 1 ), dims = 1 )
593
+ end
594
+
521
595
end
0 commit comments