Skip to content

Commit f834fde

Browse files
committed
Rely on posterior for pareto smooth tails
1 parent 9886905 commit f834fde

File tree

2 files changed

+10
-58
lines changed

2 files changed

+10
-58
lines changed

R/psis.R

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -206,62 +206,25 @@ do_psis_i <- function(log_ratios_i, tail_len_i, ...) {
206206
S <- length(log_ratios_i)
207207
# shift log ratios for safer exponentation
208208
lw_i <- log_ratios_i - max(log_ratios_i)
209-
khat <- Inf
210209

211-
if (enough_tail_samples(tail_len_i)) {
212-
ord <- sort.int(lw_i, index.return = TRUE)
213-
tail_ids <- seq(S - tail_len_i + 1, S)
214-
lw_tail <- ord$x[tail_ids]
215-
if (abs(max(lw_tail) - min(lw_tail)) < .Machine$double.eps/100) {
216-
warning(
217-
"Can't fit generalized Pareto distribution ",
218-
"because all tail values are the same.",
219-
call. = FALSE
220-
)
221-
} else {
222-
cutoff <- ord$x[min(tail_ids) - 1] # largest value smaller than tail values
223-
smoothed <- psis_smooth_tail(lw_tail, cutoff)
224-
khat <- smoothed$k
225-
lw_i[ord$ix[tail_ids]] <- smoothed$tail
226-
}
227-
}
210+
smoothed <- posterior::pareto_smooth_tail(
211+
x = lw_i,
212+
ndraws_tail = tail_len_i,
213+
tail = "right",
214+
are_log_weights = TRUE
215+
)
216+
217+
lw_i <- smoothed$x
218+
khat <- smoothed$k
228219

229220
# truncate at max of raw wts (i.e., 0 since max has been subtracted)
230221
lw_i[lw_i > 0] <- 0
231222
# shift log weights back so that the smallest log weights remain unchanged
232223
lw_i <- lw_i + max(log_ratios_i)
233224

234-
list(log_weights = lw_i, pareto_k = khat)
235-
}
236-
237-
#' PSIS tail smoothing for a single vector
238-
#'
239-
#' @noRd
240-
#' @param x Vector of tail elements already sorted in ascending order.
241-
#' @return A named list containing:
242-
#' * `tail`: vector same size as `x` containing the logs of the
243-
#' order statistics of the generalized pareto distribution.
244-
#' * `k`: scalar shape parameter estimate.
245-
#'
246-
psis_smooth_tail <- function(x, cutoff) {
247-
len <- length(x)
248-
exp_cutoff <- exp(cutoff)
249-
250-
# save time not sorting since x already sorted
251-
fit <- gpdfit(exp(x) - exp_cutoff, sort_x = FALSE)
252-
k <- fit$k
253-
sigma <- fit$sigma
254-
if (is.finite(k)) {
255-
p <- (seq_len(len) - 0.5) / len
256-
qq <- qgpd(p, k, sigma) + exp_cutoff
257-
tail <- log(qq)
258-
} else {
259-
tail <- x
260-
}
261-
list(tail = tail, k = k)
225+
list(log_weights = lw_i, pareto_k = if (is.na(khat)) Inf else khat)
262226
}
263227

264-
265228
#' Calculate tail lengths to use for fitting the GPD
266229
#'
267230
#' The number of weights (i.e., tail length) used to fit the generalized Pareto

tests/testthat/test_psis.R

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,3 @@ test_that("do_psis_i throws warning if all tail values the same", {
150150
val <- expect_warning(do_psis_i(xx, tail_len_i = 6), "all tail values are the same")
151151
expect_equal(val$pareto_k, Inf)
152152
})
153-
154-
test_that("psis_smooth_tail returns original tail values if k is infinite", {
155-
# skip on M1 Mac until we figure out why this test fails only on M1 Mac
156-
skip_if(Sys.info()[["sysname"]] == "Darwin" && R.version$arch == "aarch64")
157-
158-
xx <- c(1,2,3,4,4,4,4,4,4,4,4)
159-
val <- suppressWarnings(psis_smooth_tail(xx, 3))
160-
expect_equal(val$tail, xx)
161-
expect_equal(val$k, Inf)
162-
})
163-

0 commit comments

Comments
 (0)