@@ -116,15 +116,22 @@ loo_compare.default <- function(x, ...) {
116116 diffs <- mapply(FUN = elpd_diffs , loos [ord [1 ]], loos [ord ])
117117 elpd_diff <- apply(diffs , 2 , sum )
118118 se_diff <- apply(diffs , 2 , se_elpd_diff )
119+ # compute probabilities that a model has worse elpd than the best model
120+ # using a normal approximation (Sivula et al., 2025)
119121 p_worse <- pnorm(0 , elpd_diff , se_diff )
120122 p_worse [elpd_diff == 0 ] <- NA
121123 N <- nrow(diffs )
124+ # diagnostics to assess whether the normal approximation can be trusted
122125 if (N < 100 ) {
126+ # small N (Sivula et al., 2025)
123127 diag_pnorm <- rep(" N < 100" , length(elpd_diff ))
124128 diag_pnorm [elpd_diff == 0 ] = " "
125129 } else {
126130 diag_pnorm <- rep(" " , length(elpd_diff ))
131+ # similar predictions (Sivula et al., 2025)
127132 diag_pnorm [elpd_diff > - 4 & elpd_diff != 0 ] <- " similar predictions"
133+ # possible outliers in differences (Sivula et al., 2025;
134+ # Vehtari et al., 2024)
128135 khat_diff <- rep(NA , length(elpd_diff ))
129136 khat_diff [elpd_diff != 0 ] <- apply(diffs [,elpd_diff != 0 , drop = FALSE ], 2 , \(x ) posterior :: pareto_khat(x , tail = " both" ))
130137 diag_pnorm [khat_diff > ps_khat_threshold(N )] <- paste0(" khat_diff > " , .fr(ps_khat_threshold(N ), 2 ))
@@ -147,9 +154,10 @@ loo_compare.default <- function(x, ...) {
147154# ' @param digits For the print method only, the number of digits to use when
148155# ' printing.
149156# ' @param simplify For the print method only, should only the essential columns
150- # ' of the summary matrix be printed? The entire matrix is always returned, but
151- # ' by default only the most important columns are printed.
152- print.compare.loo <- function (x , ... , digits = 1 , simplify = TRUE ) {
157+ # ' of the summary matrix be printed? The entire matrix is always returned, bu#' @param pnorm For the print method only, should we include the normal
158+ # ' approximation based probability of model having worse performance than
159+ # ' the best model
160+ print.compare.loo <- function (x , ... , digits = 1 , simplify = TRUE , pnorm = FALSE ) {
153161 xcopy <- x
154162 if (inherits(xcopy , " old_compare.loo" )) {
155163 if (NCOL(xcopy ) > = 2 && simplify ) {
@@ -159,12 +167,16 @@ print.compare.loo <- function(x, ..., digits = 1, simplify = TRUE) {
159167 } else if (NCOL(xcopy ) > = 2 && simplify ) {
160168 xcopy <- xcopy [, c(" elpd_diff" , " se_diff" )]
161169 }
162- print(cbind(.fr(xcopy , digits ), p_worse = .fr(x [," p_worse" ],2 ), diag_pnorm = x [, " diag_pnorm" ]), quote = FALSE )
163- invisible (x )
170+ if (p_worse ) {
171+ print(cbind(.fr(xcopy , digits ), p_worse = .fr(x [," p_worse" ],2 ), diag_pnorm = x [, " diag_pnorm" ]), quote = FALSE )
172+ invisible (x )
173+ } else {
174+ print(cbind(.fr(xcopy , digits ), quote = FALSE ))
175+ invisible (x )
176+ }
164177}
165178
166179
167-
168180# internal ----------------------------------------------------------------
169181
170182# ' Compute pointwise elpd differences
0 commit comments