Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsAPI = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"

[weakdeps]
Optim = "429524aa-4258-5aef-a3af-852621145aeb"

[extensions]
DistributionFitsOptimExt = "Optim"

[compat]
Distributions = "0.25"
FillArrays = "0.12, 0.13, 1"
Optim = "1.7"
Reexport = "1.2"
Requires = "1.2"
StaticArrays = "1.2"
StatsBase = "0.33, 0.34"
StatsFuns = "0.9, 1"
StatsAPI = "1"
julia = "1.6"

[extensions]
DistributionFitsOptimExt = "Optim"

[extras]
Optim = "429524aa-4258-5aef-a3af-852621145aeb"

[weakdeps]
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
11 changes: 7 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ makedocs(;
pages=[
"Home" => "index.md",
"Dependencies" => "set_optimize.md",
"LogNormal" => "lognormal.md",
"LogitNormal" => "logitnormal.md",
"Weibull" => "weibull.md",
"Gamma" => "gamma.md",
"Distributions" => [
"LogNormal" => "lognormal.md",
"LogitNormal" => "logitnormal.md",
"Weibull" => "weibull.md",
"Gamma" => "gamma.md",
],
"API" => "api.md",
#"Details" => "z_autodocs.md",
],
)
Expand Down
25 changes: 25 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# API
## AbstractMoments

The concept of first and higher order moments is
captured by its own type. This allows dispatching
the fit method.

```@docs
AbstractMoments
moments
```

## QuantilePoint

The concept of a pair (p,q), i.e. a probability in [0,1] and associated quantile
is captured by its own type. This allows dispatching
the fit method.

```@docs
QuantilePoint
```




6 changes: 0 additions & 6 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,6 @@ fit(::Type{D}, ::AbstractMoments) where {D<:Distribution}
moments(d::Distribution, ::Val{N} = Val(2)) where N
```

The syntax `Moments(mean,var)` produces an object of type `Moments <: AbstractMoments`.

```@docs
AbstractMoments{N}
```

## Fit to several quantile points

```@docs
Expand Down
2 changes: 1 addition & 1 deletion docs/src/lognormal.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ true
```

```@docs
fit(::Type{LogNormal}, ::Any, ::Σstar)
fit(::Type{LogNormal}, ::Any, ::AbstractΣstar)
```

```@docs
Expand Down
23 changes: 21 additions & 2 deletions docs/src/z_autodocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ Documentation for [DistributionFits](https://github.com/bgctw/DistributionFits.j
```@index
```

```@autodocs
Modules = [DistributionFits]
[comment]: # (```@autodocs)

[comment]: # (Modules = [DistributionFits])

[comment]: # (```)


taken care of in index.md
called only internally from fit, documented in docstring via ","
```@docs
fit_median_quantile
fit_mean_quantile
fit_mode_quantile
```

internals
```@docs
meanFunOfProb
ofLogitNormalModeUpper
```
[comment]: # (fit(Type{LogNormal}, Any, AbstractΣstar))

6 changes: 5 additions & 1 deletion src/DistributionFits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ using Reexport

using FillArrays, StaticArrays
using StatsFuns: logit, logistic, normcdf
#using Infiltrator

if !isdefined(Base, :get_extension)
using Requires
end

# for extension
import Distributions: mean, var, mode
import StatsBase: fit
#import StatsBase: fit
import StatsAPI: fit
# Moments also extends getindex, mean, kurtorsis ....

export
Expand All @@ -22,6 +24,8 @@ export
fit_mean_quantile, fit_mode_quantile, fit_median_quantile,
@qp, @qp_ll, @qp_l, @qp_m, @qp_u, @qp_uu,
@qs_cf90, @qs_cf95,
qp, qp_ll, qp_l, qp_m, qp_u, qp_uu,
qs_cf90, qs_cf95,
fit_mean_relerror

# document but do not export - need to qualify by 'DistributionFits.'
Expand Down
69 changes: 52 additions & 17 deletions src/fitstats.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Base.convert(::Type{AbstractArray}, m::Moments) = m.all

Get the first N moments of a distribution.

See also type [`AbstractMoments`](@ref).
Procudes an object of type [`AbstractMoments`](@ref).

## Examples
```julia
Expand Down Expand Up @@ -116,7 +116,32 @@ fit(::Type{D}, m::AbstractMoments) where {D<:Distribution} =
error("fitting to moments not implemented for distribution of type $D")


"""
QuantilePoint

A representation of a pair (p,q), i.e. (percentile,quantile).

# Notes
Several macros help to construct QuantilePoints
- `@qp(q,p)` quantile at specified p: `QuantilePoint(q,p)`

For Float64-based percentiles there are shortcuts
- `@qp_ll(q0_025)` quantile at very low p: `QuantilePoint(q0_025,0.025)`
- `@qp_l(q0_05)` quantile at low p: `QuantilePoint(q0_05,0.05)`
- `@qp_m(median)` quantile at median: `QuantilePoint(median,0.5)`
- `@qp_u(q0_95)` quantile at high p: `QuantilePoint(q0_95,0.95)`
- `@qp_uu(q0_975)` quantile at very high p: `QuantilePoint(q0_975,0.975)`

For constructing QuantilePoints with type of percentiles other than Float64,
use the corresponding functions, that create a percentiles of the type
of qiven quantile.
E.g. for a Float32-based QuantilePoint at ver low percentile
- `qp_ll(0.2f0)` constructs a `QuantilePoint(0.2f0,0.025f0)`

There are macros/functions for some commonly used sets of QuantilePoints: 90% and 95% confidence intervals:
- `@qs_cf90(q0_05,q0_95)`
- `@qs_cf95(q0_025,q0_975)` -> `Set([QuantilePoint(q0_025,0.025),QuantilePoint(q0_975,0.975)]))`
"""
struct QuantilePoint{TQ,TP}
q::TQ
p::TP
Expand Down Expand Up @@ -149,26 +174,31 @@ macro qs_cf90(q0_05,q0_95)
macro qs_cf95(q0_025,q0_975)
:(Set([QuantilePoint($(esc(q0_025)),0.025),QuantilePoint($(esc(q0_975)),0.975)])) end

# The non-macro versions return percentile whose type matches that of the argument
qp_ll(q0_025::T) where T = QuantilePoint(q0_025, T(0.025))
qp_l(q0_05::T) where T = QuantilePoint(q0_05, T(0.05))
qp_m(median::T) where T = QuantilePoint(median, T(0.5))
qp_u(q0_95::T) where T = QuantilePoint(q0_95, T(0.95))
qp_uu(q0_975::T) where T = QuantilePoint(q0_975, T(0.975))

function qs_cf90(q0_05::T,q0_95::T) where T
Set([QuantilePoint(q0_05,T(0.05)),QuantilePoint(q0_95,T(0.95))])
end
function qs_cf95(q0_025::T,q0_975::T) where T
Set([QuantilePoint(q0_025,T(0.025)),QuantilePoint(q0_975,T(0.975))])
end


"""
fit(D, lower, upper)
fit(D, lower::QuantilePoint, upper::QuantilePoint)

Fit a statistical distribution to a set of quantiles

# Arguments
- `D`: The type of the distribution to fit
- `lower`: lower QuantilePoint (p,q)
- `lower`: lower [`QuantilePoint`](@ref) (p,q)
- `upper`: upper QuantilePoint (p,q)

# Notes
Several macros help to construct QuantilePoints
- `@qp(q,p)` quantile at specified p: `QuantilePoint(q,p)`
- `@qp_ll(q0_025)` quantile at very low p: `QuantilePoint(q0_025,0.025)`
- `@qp_l(q0_05)` quantile at low p: `QuantilePoint(q0_05,0.05)`
- `@qp_m(median)` quantile at median: `QuantilePoint(median,0.5)`
- `@qp_u(q0_95)` quantile at high p: `QuantilePoint(q0_95,0.95)`
- `@qp_uu(q0_975)` quantile at very high p: `QuantilePoint(q0_975,0.975)`

# Examples
```jldoctest; output = false, setup = :(using Statistics,Distributions)
d = fit(LogNormal, @qp_m(3), @qp_uu(5));
Expand All @@ -179,12 +209,10 @@ true
"""
function fit(::Type{D}, lower::QuantilePoint, upper::QuantilePoint) where D<:Distribution
error("fitting to two quantile points not implemented for distribution of type $D")
end,
function fit_median_quantile(D::Type{DT}, median, qp::QuantilePoint) where {DT <: Distribution}
return(fit(D, @qp_m(median), qp))
end



"""
fit(D, val, qp, ::Val{stats} = Val(:mean))

Expand Down Expand Up @@ -217,12 +245,19 @@ function fit(::Type{D}, val, qp::QuantilePoint, ::Val{stats} = Val(:mean)) where
stats == :median && return(fit_median_quantile(D, val, qp))
error("unknown stats: $stats")
end,
function fit_mean_quantile(::Type{D}, mean::Real, qp::QuantilePoint) where D<:Distribution
function fit_median_quantile(D::Type{DT}, median, qp::QuantilePoint) where {DT <: Distribution}
return(fit(D, @qp_m(median), qp))
end,
function fit_mean_quantile(d::Type{D}, mean::Real, qp::QuantilePoint) where D<:Distribution
error("fit_mean_quantile not yet implemented for Distribution of type: $D")
end
end,
function fit_mode_quantile(::Type{D}, mode::Real, qp::QuantilePoint) where D<:Distribution
error("fit_mode_quantile not yet implemented for Distribution of type: $D")
end

# function fit_mean_quantile(d::Type{D}, mean::Real, qp::QuantilePoint) where D<:Distribution
# error("fit_mean_quantile not yet implemented for Distribution of type: $D")
# end



12 changes: 12 additions & 0 deletions test/fitstats.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,20 @@ end;
@test @qs_cf90(0.2,0.7) == Set([@qp_l(0.2),@qp_u(0.7)])
@test @qs_cf95(0.2,0.7) == Set([@qp_ll(0.2),@qp_uu(0.7)])
end;
@testset "functions for Float32" begin
@test @qp(0.4f0,0.7f0) == QuantilePoint(0.4f0,0.7f0)
@test qp_ll(0.7f0) == QuantilePoint(0.7f0,0.025f0)
@test qp_l(0.7f0) == QuantilePoint(0.7f0,0.05f0)
@test qp_m(0.7f0) == QuantilePoint(0.7f0,0.5f0)
@test qp_u(0.7f0) == QuantilePoint(0.7f0,0.95f0)
@test qp_uu(0.7f0) == QuantilePoint(0.7f0,0.975f0)
@test qs_cf90(0.2f0,0.7f0) == Set([qp_l(0.2f0),qp_u(0.7f0)])
@test qs_cf95(0.2f0,0.7f0) == Set([qp_ll(0.2f0),qp_uu(0.7f0)])
end;
end;



@testset "global fit functions" begin
@test_throws ErrorException fit(Distribution, Moments())
qpl = @qp_m(3)
Expand Down