Skip to content

Commit

Permalink
Merge pull request #136 from jojal5/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
jojal5 authored Feb 10, 2025
2 parents c298432 + 4a936be commit 60b8cb5
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Extremes"
uuid = "fe3fe864-1b39-11e9-20b8-1f96fa57382d"
authors = ["Jonathan Jalbert <[email protected]>"]
version = "1.0.2"
version = "1.0.3"

[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ The datasets that are available through this package are the datasets referenced
They were obtained using the R package `ismev`.
https://www.rdocumentation.org/packages/ismev/

## Lightweight fit functions

The package also provides fit functions using maximum likelihood and probability-weighted moments for the Generalized Extreme Value, Gumbel, and Generalized Pareto distributions. They can be used with the `fit` function for the corresponding type in `Distributions.jl`. For example:

```julia
julia> using Distributions, Extremes

y = rand(GeneralizedExtremeValue(0,1,.1))

fit(GeneralizedExtremeValue, y)
fit(GeneralizedExtremeValue, y, method="mle")
fit(GeneralizedExtremeValue, y, method="pwm")
```

## How to cite this library
Jalbert, J., Farmer, M., Gobeil, G., & Roy, P. (2024). Extremes.jl: Extreme Value Analysis in Julia. Journal of Statistical Software, 109(6), 1–35. https://doi.org/10.18637/jss.v109.i06

Expand Down
3 changes: 3 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@
- Refactor Hessian computations with PDMats.
- Implement generic Delta method using PDMats.

## 1.0.3
- Add lightweight functions for simple fit of Generalized Extreme Value, Gumbel and Generalized Pareto distributions. See [`Extremes.fit`](@ref).

## Nightly
3 changes: 2 additions & 1 deletion src/Extremes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ using Gadfly
import CSV
import ForwardDiff, SpecialFunctions

import Distributions: insupport, location, logpdf, maximum, minimum, params, pdf, quantile, scale, shape
import Distributions: fit, fit_mle, insupport, location, logpdf, maximum, minimum, params, pdf, quantile, scale, shape
import Statistics.var
import Base.length, Base.maximum, Base.sum

Expand Down Expand Up @@ -44,6 +44,7 @@ export
getcluster,

# Fitting functions
fit,
gevfit,
gevfitbayes,
gevfitpwm,
Expand Down
2 changes: 2 additions & 0 deletions src/parameterestimation.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include(joinpath("parameterestimation", "bayesian.jl"))
include(joinpath("parameterestimation", "maximumlikelihood.jl"))
include(joinpath("parameterestimation", "probabilityweightedmoment.jl"))
include(joinpath("parameterestimation", "lightweight_functions.jl"))

119 changes: 119 additions & 0 deletions src/parameterestimation/lightweight_functions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
function fit_mle(pd::Type{<:GeneralizedExtremeValue}, y::Vector{<:Real})

fm = gevfit(y)
fd = Extremes.getdistribution(fm)[]

return fd
end

function fit_pwm(pd::Type{<:GeneralizedExtremeValue}, y::Vector{<:Real})

fm = gevfitpwm(y)
fd = Extremes.getdistribution(fm)[]

return fd
end

"""
fit(pd::Type{<:GeneralizedExtremeValue}, y::Vector{<:Real}; method::String="mle")
Fit the Generalized Extreme Value distribution to the data vector `y`.
## Details
This function estimates the parameters of the GEV distribution from an identically distributed random sample. It is a lightweight feature of the Extremes.jl library.
In the presence of non-stationarity or for advanced inference, the [`gevfit`](@ref) function is more appropriate.
The `method` argument allows selecting the estimation method: `mle` for maximum likelihood estimation or `pwm` for the probability-weighted moments method.
"""
function fit(pd::Type{<:GeneralizedExtremeValue}, y::Vector{<:Real}; method::String="mle")
@assert method ("mle", "pwm") "Method $method is not a valid method among mle and pwm."

if method == "mle"
return fit_mle(pd, y)
else
return fit_pwm(pd, y)
end

end

function fit_mle(pd::Type{<:Gumbel}, y::Vector{<:Real})

fm = gumbelfit(y)
fd = Extremes.getdistribution(fm)[]

return fd
end

function fit_pwm(pd::Type{<:Gumbel}, y::Vector{<:Real})

fm = gumbelfitpwm(y)
fd = Extremes.getdistribution(fm)[]

return fd
end

"""
fit(pd::Type{<:Gumbel}, y::Vector{<:Real}; method::String="mle")
Fit the Gumbel distribution to the data vector `y`.
## Details
This function estimates the parameters of the Gumbel distribution from an identically distributed random sample. It is a lightweight feature of the Extremes.jl library.
In the presence of non-stationarity or for advanced inference, the [`gevfit`](@ref) function is more appropriate.
The `method` argument allows selecting the estimation method: `mle` for maximum likelihood estimation or `pwm` for the probability-weighted moments method.
"""
function fit(pd::Type{<:Gumbel}, y::Vector{<:Real}; method::String="mle")
@assert method ("mle", "pwm") "Method $method is not a valid method among mle and pwm."

if method == "mle"
return fit_mle(pd, y)
else
return fit_pwm(pd, y)
end

end

function fit_mle(pd::Type{<:GeneralizedPareto}, y::Vector{<:Real})

fm = gpfit(y)
fd = Extremes.getdistribution(fm)[]

return fd
end

function fit_pwm(pd::Type{<:GeneralizedPareto}, y::Vector{<:Real})

fm = gpfitpwm(y)
fd = Extremes.getdistribution(fm)[]

return fd
end

"""
fit(pd::Type{<:GeneralizedPareto}, y::Vector{<:Real}; method::String="mle")
Fit the Generalized Pareto distribution to the exceedences vector `y`.
## Details
This function estimates the parameters of the GP distribution from an identically distributed random sample. It is a lightweight feature of the Extremes.jl library.
In the presence of non-stationarity or for advanced inference, the [`gpfit`](@ref) function is more appropriate.
The `method` argument allows selecting the estimation method: `mle` for maximum likelihood estimation or `pwm` for the probability-weighted moments method.
"""
function fit(pd::Type{<:GeneralizedPareto}, y::Vector{<:Real}; method::String="mle")
@assert method ("mle", "pwm") "Method $method is not a valid method among mle and pwm."

if method == "mle"
return fit_mle(pd, y)
else
return fit_pwm(pd, y)
end

end
57 changes: 57 additions & 0 deletions test/parameterestimation/lightweight_functions_test.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@testset "lightweight_functions.m" begin

@testset "fit(GeneralizedExtremeValue, y).jl" begin

df = CSV.read("dataset/gev_stationary.csv", DataFrame)
y = df.y

# Assert estimation method
@test_throws AssertionError fit(GeneralizedExtremeValue, y, method = "unsupported")

fm_mle = Extremes.fit_mle(GeneralizedExtremeValue, y)

@test all(isapprox.(params(fm_mle),(0.0009, exp(0.0142), -0.0060), atol=.0001))

fm_pwm = Extremes.fit_pwm(GeneralizedExtremeValue, y)

@test all(isapprox.(params(fm_pwm),(-0.0005, exp(0.0125), -0.0033), atol=.0001))

end

@testset "fit(Gumbel, y).jl" begin

df = CSV.read("dataset/gev_stationary.csv", DataFrame)
y = df.y

# Assert estimation method
@test_throws AssertionError fit(Gumbel, y, method = "unsupported")

fm_mle = Extremes.fit_mle(Gumbel, y)

@test all(isapprox.(params(fm_mle),(-0.0023, exp(0.0124)), atol=.0001))

fm_pwm = Extremes.fit_pwm(Gumbel, y)

@test all(isapprox.(params(fm_pwm),(-0.0020, exp(0.0095)), atol=.0001))

end

@testset "fit(GeneralizedPareto, y).jl" begin

df = CSV.read("dataset/gp_stationary.csv", DataFrame)
y = df.y

# Assert estimation method
@test_throws AssertionError fit(GeneralizedPareto, y, method = "unsupported")

fm_mle = Extremes.fit_mle(GeneralizedPareto, y)

@test all(isapprox.(params(fm_mle), (0., exp(-0.0135), 0.0059), atol=.0001))

fm_pwm = Extremes.fit_pwm(GeneralizedPareto, y)

@test all(isapprox.(params(fm_pwm),(0., exp(-0.0199), 0.0122), atol=.0001))

end

end
2 changes: 1 addition & 1 deletion test/parameterestimation_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
include(joinpath("parameterestimation", "bayesian_test.jl"))
include(joinpath("parameterestimation", "maximumlikelihood_test.jl"))
include(joinpath("parameterestimation", "probabilityweightedmoment_test.jl"))

include(joinpath("parameterestimation", "lightweight_functions_test.jl"))
end
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
ci = cint(rl)

@testset "getdistribution(fittedmodel)" begin
@test all(vec(Extremes.getdistribution(fm)) .== pd)
@test all(vec(Extremes.getdistribution(fm)) . pd)
end


Expand Down

2 comments on commit 60b8cb5

@jojal5
Copy link
Owner Author

@jojal5 jojal5 commented on 60b8cb5 Feb 10, 2025

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/124744

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.0.3 -m "<description of version>" 60b8cb5d51bfa4a4edff5323aa1e0292d0095f8d
git push origin v1.0.3

Please sign in to comment.