Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add loglogistic distribution #1780

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

yunzli
Copy link

@yunzli yunzli commented Sep 19, 2023

This PR adds log-logistic distribution to the package.

The log-logistic distribution has two parameters: scale and shape. It has been widely used in survival analysis.

The model implementation is in src/univariate/continuous/loglogistic.jl
The test is in test/univariate/continuous/loglogistic.jl

@codecov-commenter
Copy link

codecov-commenter commented Sep 19, 2023

Codecov Report

Attention: 23 lines in your changes are missing coverage. Please review.

Files Coverage Δ
src/Distributions.jl 100.00% <ø> (ø)
src/univariates.jl 75.90% <ø> (ø)
src/univariate/continuous/loglogistic.jl 43.90% <43.90%> (ø)

... and 10 files with indirect coverage changes

📢 Thoughts on this report? Let us know!.

@ParadaCarleton
Copy link
Contributor

This looks like a pretty solid implementation, but I do wonder if we should be adding Log* distributions piecemeal like this, rather than providing a more general interface for transformed variables.

@yunzli
Copy link
Author

yunzli commented Sep 22, 2023

This looks like a pretty solid implementation, but I do wonder if we should be adding Log* distributions piecemeal like this, rather than providing a more general interface for transformed variables.

It sounds like a very interesting idea to provide a general interface for transformed variables. But I feel there might be some difficulties. 1) commonly used parameterization might not be consistent for distribution on R and its log transformation on R+. 2) it might not be straightforward to "translate" moments. For example, Logistic(a, b) always has a mean value of a, but LogLogistic(c,d) doesn't always have a finite mean. 3) It might be redundant for users to recreate a transformation, especially for popular ones as LogNormal, LogLogistic, LogUniform, etc.

src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved
src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved
src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved

```julia
LogLogistic() # Log-logistic distribution with unit scale and unit shape
LogLogistic(θ) # Log-logistic distribution with scale θ and unit shape
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned calling theta the "scale" parameter might confuse users, since the scale parameter is exp(location) in this case.

Copy link
Member

@devmotion devmotion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR!

I haven't checked the math yet but commented on a few Julia issues that we should fix before merging the PR.

It's good that you added tests! We already have quite extensive automatic tests for distributions but that requires that you add reference values using R to test/refs. Can you fix that?

@distr_support LogLogistic 0.0 Inf

#### Coversions
convert(::Type{LogLogistic{T}}, θ::S, ϕ::S) where {T <: Real, S <: Real} = LogLogistic(T(θ), T(ϕ))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor already exists for this purpose:

Suggested change
convert(::Type{LogLogistic{T}}, θ::S, ϕ::S) where {T <: Real, S <: Real} = LogLogistic(T(θ), T(ϕ))


#### Coversions
convert(::Type{LogLogistic{T}}, θ::S, ϕ::S) where {T <: Real, S <: Real} = LogLogistic(T(θ), T(ϕ))
convert(::Type{LogLogistic{T}}, d::LogLogistic{S}) where {T <: Real, S <: Real} = LogLogistic(T(d.θ), T(d.ϕ), check_args=false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not completely correct as it does not guarantee that you get the desired type, and it's missing the case when the type is already correct:

Suggested change
convert(::Type{LogLogistic{T}}, d::LogLogistic{S}) where {T <: Real, S <: Real} = LogLogistic(T(d.θ), T(d.ϕ), check_args=false)
convert(::Type{LogLogistic{T}}, d::LogLogistic{T}) where {T<:Real} = d
convert(::Type{LogLogistic{T}}, d::LogLogistic) where {T<:Real} = LogLogistic{T}(T(d.θ), T(d.ϕ))

if d.ϕ ≤ 1
error("mean is defined only when ϕ > 1")
end
return d.θ*π/d.ϕ/sin(π/d.ϕ)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to use

Suggested change
return d.θ*π/d.ϕ/sin/d.ϕ)
return d.θ/sinc(1/d.ϕ)

src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved
#### Evaluation
function pdf(d::LogLogistic, x::Real)
if x ≤ zero(0)
z = zero(x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a type instability, generally the two branches yield z of different types.

src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved

function var(d::LogLogistic)
if d.ϕ ≤ 2
erros("var is defined only when ϕ > 2")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.


function logcdf(d::LogLogistic, x::Real)
if x <= 0
-Inf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it was supposed to be

        return -Inf

But that would again create a type instability.

src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved
src/univariate/continuous/loglogistic.jl Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants