Skip to content

Commit

Permalink
Fix quantile and cdf for monotonically decreasing transformations
Browse files Browse the repository at this point in the history
Resolves #100
  • Loading branch information
mitchelloharawild committed Apr 5, 2024
1 parent 96b8f40 commit c06b7e9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
9 changes: 6 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
## Bug fixes

* Fixed error when using '-' as a unary operator on a distribution different from
`dist_normal()` by @venpopov (#95)
`dist_normal()` (@venpopov, #95)
* Density for transformed distributions now correctly gives 0 instead of NaNs for
values outside the support of the distribution (#97); by @venpopov
values outside the support of the distribution (@venpopov, #97)
* Fixed `quantile()` and `cdf()` for transformed distributions with
monotonically decreasing transformations (#100).

## New features

* support() now shows whether the interval of support is open or closed (#97); by @venpopov
* `support()` now shows whether the interval of support is open or
closed (@venpopov, #97)

# distributional 0.4.0

Expand Down
8 changes: 8 additions & 0 deletions R/transformed.R
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ density.dist_transformed <- function(x, at, ...){
cdf.dist_transformed <- function(x, q, ...){
inv <- function(v) suppressWarnings(x[["inverse"]](v))
p <- cdf(x[["dist"]], inv(q), ...)
if(!monotonic_increasing(x[["transform"]], support(x[["dist"]]))) p <- 1 - p
limits <- field(support(x), "lim")[[1]]
if (!any(is.na(limits))) {
p[q <= limits[1]] <- 0
Expand All @@ -78,6 +79,7 @@ cdf.dist_transformed <- function(x, q, ...){

#' @export
quantile.dist_transformed <- function(x, p, ...){
if(!monotonic_increasing(x[["transform"]], support(x[["dist"]]))) p <- 1 - p
x[["transform"]](quantile(x[["dist"]], p, ...))
}

Expand Down Expand Up @@ -153,3 +155,9 @@ Ops.dist_transformed <- function(e1, e2) {

vec_data(dist_transformed(wrap_dist(list(list(e1,e2)[[which(is_dist)[1]]][["dist"]])), trans, inverse))[[1]]
}

monotonic_increasing <- function(f, support) {
# Currently assumes (without checking, #9) monotonicity of f over the domain
x <- f(field(support, "lim")[[1]])
x[[2L]] > x[[1L]]
}
24 changes: 24 additions & 0 deletions tests/testthat/test-transformations.R
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,27 @@ test_that("transformed distributions pdf integrates to 1", {
}
})


test_that("monotonically decreasing transformations (#100)", {
dist <- dist_lognormal()

expect_equal(
quantile(-dist, 0.2), -quantile(dist, 1 - 0.2)
)
expect_equal(
quantile(1/dist, 0.2), 1/quantile(dist, 1 - 0.2)
)
expect_equal(
quantile(-1/dist, 0.7), -1/quantile(dist, 0.7)
)

expect_equal(
cdf(-dist, -2), 1 - cdf(dist, 2)
)
expect_equal(
cdf(1/dist, 2), 1 - cdf(dist, 1/2)
)
expect_equal(
cdf(-1/dist, -2), cdf(dist, 1/2)
)
})

0 comments on commit c06b7e9

Please sign in to comment.