From 5d0f1bdb7a42a498898063bdbd7b04f5bdff86e1 Mon Sep 17 00:00:00 2001 From: David Widmann Date: Fri, 11 Apr 2025 20:42:46 +0200 Subject: [PATCH] Remove `median(::MvLogNormal)` --- docs/src/multivariate.md | 3 +-- src/multivariate/mvlognormal.jl | 24 ++++-------------------- test/multivariate/mvlognormal.jl | 15 --------------- 3 files changed, 5 insertions(+), 37 deletions(-) diff --git a/docs/src/multivariate.md b/docs/src/multivariate.md index 35eff32caa..a5a3093d65 100644 --- a/docs/src/multivariate.md +++ b/docs/src/multivariate.md @@ -84,11 +84,10 @@ In addition to the methods listed in the common interface above, we also provide ```@docs location(::MvLogNormal) scale(::MvLogNormal) -median(::MvLogNormal) mode(::MvLogNormal) ``` -It can be necessary to calculate the parameters of the lognormal (location vector and scale matrix) from a given covariance and mean, median or mode. To that end, the following functions are provided. +It can be necessary to calculate the parameters of the lognormal (location vector and scale matrix) from a given covariance and mean or mode. To that end, the following functions are provided. ```@docs location{D<:Distributions.AbstractMvLogNormal}(::Type{D},s::Symbol,m::AbstractVector,S::AbstractMatrix) diff --git a/src/multivariate/mvlognormal.jl b/src/multivariate/mvlognormal.jl index 1eecd38c2f..04548f4803 100644 --- a/src/multivariate/mvlognormal.jl +++ b/src/multivariate/mvlognormal.jl @@ -14,7 +14,6 @@ # - _logpdf(d,x) Evaluate logarithm of pdf # - _pdf(d,x) Evaluate the pdf # - mean(d) Mean of the distribution -# - median(d) Median of the distribution # - mode(d) Mode of the distribution # - var(d) Vector of element-wise variance # - cov(d) Covariance matrix @@ -58,13 +57,6 @@ function _location!(::Type{D},::Type{Val{:mean}},mn::AbstractVector,S::AbstractM μ end -function _location!(::Type{D},::Type{Val{:median}},md::AbstractVector,S::AbstractMatrix,μ::AbstractVector) where D<:AbstractMvLogNormal - @simd for i=1:length(md) - @inbounds μ[i] = log(md[i]) - end - μ -end - function _location!(::Type{D},::Type{Val{:mode}},mo::AbstractVector,S::AbstractMatrix,μ::AbstractVector) where D<:AbstractMvLogNormal @simd for i=1:length(mo) @inbounds μ[i] = log(mo[i]) + S[i,i] @@ -72,7 +64,7 @@ function _location!(::Type{D},::Type{Val{:mode}},mo::AbstractVector,S::AbstractM μ end -###Functions to calculate location and scale for a distribution with desired :mean, :median or :mode and covariance +###Functions to calculate location and scale for a distribution with desired :mean or :mode and covariance """ location!{D<:AbstractMvLogNormal}(::Type{D},s::Symbol,m::AbstractVector,S::AbstractMatrix,μ::AbstractVector) @@ -91,12 +83,11 @@ Calculate the location vector (the mean of the underlying normal distribution). - If `s == :meancov`, then m is taken as the mean, and S the covariance matrix of a lognormal distribution. -- If `s == :mean | :median | :mode`, then m is taken as the mean, median or +- If `s == :mean | :mode`, then m is taken as the mean or mode of the lognormal respectively, and S is interpreted as the scale matrix (the covariance of the underlying normal distribution). -It is not possible to analytically calculate the location vector from e.g., median + covariance, -or from mode + covariance. +It is not possible to analytically calculate the location vector from e.g. from mode + covariance. """ function location(::Type{D},s::Symbol,m::AbstractVector,S::AbstractMatrix) where D<:AbstractMvLogNormal @assert size(S) == (length(m),length(m)) @@ -209,17 +200,10 @@ scale(d::MvLogNormal) = cov(d.normal) #See https://en.wikipedia.org/wiki/Log-normal_distribution mean(d::MvLogNormal) = exp.(mean(d.normal) .+ var(d.normal)/2) -""" - median(d::MvLogNormal) - -Return the median vector of the lognormal distribution. which is strictly smaller than the mean. -""" -median(d::MvLogNormal) = exp.(mean(d.normal)) - """ mode(d::MvLogNormal) -Return the mode vector of the lognormal distribution, which is strictly smaller than the mean and median. +Return the mode vector of the lognormal distribution, which is strictly smaller than the mean. """ mode(d::MvLogNormal) = exp.(mean(d.normal) .- var(d.normal)) function cov(d::MvLogNormal) diff --git a/test/multivariate/mvlognormal.jl b/test/multivariate/mvlognormal.jl index af887f40d0..85d788a24c 100644 --- a/test/multivariate/mvlognormal.jl +++ b/test/multivariate/mvlognormal.jl @@ -11,28 +11,20 @@ function test_mvlognormal(g::MvLogNormal, n_tsamples::Int=10^6, rng::Union{AbstractRNG, Missing} = missing) d = length(g) mn = mean(g) - md = median(g) mo = mode(g) S = cov(g) s = var(g) e = entropy(g) @test partype(g) == Float64 @test isa(mn, Vector{Float64}) - if g.normal.μ isa Zeros{Float64,1} - @test md isa FillArrays.AbstractFill{Float64,1} - else - @test md isa Vector{Float64} - end @test isa(mo, Vector{Float64}) @test isa(s, Vector{Float64}) @test isa(S, Matrix{Float64}) @test length(mn) == d - @test length(md) == d @test length(mo) == d @test length(s) == d @test size(S) == (d, d) @test s ≈ diag(S) - @test md ≈ exp.(mean(g.normal)) @test mn ≈ exp.(mean(g.normal) .+ var(g.normal)/2) @test mo ≈ exp.(mean(g.normal) .- var(g.normal)) @test entropy(g) ≈ d*(1 + Distributions.log2π)/2 + logdetcov(g.normal)/2 + sum(mean(g.normal)) @@ -50,15 +42,11 @@ function test_mvlognormal(g::MvLogNormal, n_tsamples::Int=10^6, X = rand(rng, g, n_tsamples) end emp_mn = vec(mean(X, dims=2)) - emp_md = vec(median(X, dims=2)) Z = X .- emp_mn emp_cov = (Z * Z') ./ n_tsamples for i = 1:d @test isapprox(emp_mn[i] , mn[i] , atol=(sqrt(s[i] / n_tsamples) * 8.0)) end - for i = 1:d - @test isapprox(emp_md[i] , md[i] , atol=(sqrt(s[i] / n_tsamples) * 8.0)) - end for i = 1:d, j = 1:d @test isapprox(emp_cov[i,j], S[i,j], atol=(sqrt(s[i] * s[j]) * 20.0) / sqrt(n_tsamples)) end @@ -76,13 +64,11 @@ function test_mvlognormal(g::MvLogNormal, n_tsamples::Int=10^6, # test the location and scale functions @test isapprox(location(g), location(MvLogNormal,:meancov,mean(g),cov(g)) , atol=1e-8) @test isapprox(location(g), location(MvLogNormal,:mean,mean(g),scale(g)) , atol=1e-8) - @test isapprox(location(g), location(MvLogNormal,:median,median(g),scale(g)), atol=1e-8) @test isapprox(location(g), location(MvLogNormal,:mode,mode(g),scale(g)) , atol=1e-8) @test isapprox(scale(g) , scale(MvLogNormal,:meancov,mean(g),cov(g)) , atol=1e-8) @test isapprox(location(g), location!(MvLogNormal,:meancov,mean(g),cov(g),zero(mn)) , atol=1e-8) @test isapprox(location(g), location!(MvLogNormal,:mean,mean(g),scale(g),zero(mn)) , atol=1e-8) - @test isapprox(location(g), location!(MvLogNormal,:median,median(g),scale(g),zero(mn)), atol=1e-8) @test isapprox(location(g), location!(MvLogNormal,:mode,mode(g),scale(g),zero(mn)) , atol=1e-8) @test isapprox(scale(g) , Distributions.scale!(MvLogNormal,:meancov,mean(g),cov(g),zero(S)), atol=1e-8) @@ -99,7 +85,6 @@ end l1 = LogNormal(0.1, 0.4) l2 = MvLogNormal([0.1], 0.16 * I) @test [mean(l1)] ≈ mean(l2) - @test [median(l1)] ≈ median(l2) @test [mode(l1)] ≈ mode(l2) @test [var(l1)] ≈ var(l2) @test entropy(l1) ≈ entropy(l2)