Skip to content

Commit 55f5e2d

Browse files
committed
support for geometric distribution
1 parent 6971b8a commit 55f5e2d

File tree

4 files changed

+49
-9
lines changed

4 files changed

+49
-9
lines changed

src/MixedModels.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ using BSplineKit: interpolate
77
using Compat: @compat
88
using DataAPI: DataAPI, levels, refpool, refarray, refvalue
99
using Distributions: Distributions, Bernoulli, Binomial, Chisq, Distribution, Gamma
10-
using Distributions: InverseGaussian, Normal, Poisson, ccdf
10+
using Distributions: Geometric, InverseGaussian, Normal, Poisson, ccdf
1111
using GLM: GLM, GeneralizedLinearModel, IdentityLink, InverseLink, LinearModel
1212
using GLM: Link, LogLink, LogitLink, ProbitLink, SqrtLink
1313
using GLM: canonicallink, glm, linkinv, dispersion, dispersion_parameter
@@ -55,6 +55,7 @@ export @formula,
5555
Grouping,
5656
Gamma,
5757
GeneralizedLinearMixedModel,
58+
Geometric,
5859
HelmertCoding,
5960
HypothesisCoding,
6061
IdentityLink,

src/generalizedlinearmixedmodel.jl

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,20 @@ function GeneralizedLinearMixedModel(
383383
)
384384
end
385385

386+
_distwarn(::T) where T <: Union{Bernoulli,Binomial,Poisson} = nothing
387+
function _distwarn(::T) where T <: Union{Gamma,InverseGaussian,Normal}
388+
@warn """Results for families with a dispersion parameter are not reliable.
389+
It is best to avoid trying to fit such models in MixedModels until
390+
the authors gain a better understanding of those cases."""
391+
return nothing
392+
end
393+
394+
function _distwarn(::Geometric)
395+
@warn "The results for geometric family models have not been confirmed to be reliable."
396+
end
397+
398+
_distwarn(::T) where {T <: Distribution} = error("$(nameof(T)) distribution is not supported")
399+
386400
function GeneralizedLinearMixedModel(
387401
f::FormulaTerm,
388402
tbl::Tables.ColumnTable,
@@ -400,11 +414,7 @@ function GeneralizedLinearMixedModel(
400414
ArgumentError("use LinearMixedModel for Normal distribution with IdentityLink")
401415
)
402416

403-
if !any(isa(d, dist) for dist in (Bernoulli, Binomial, Poisson))
404-
@warn """Results for families with a dispersion parameter are not reliable.
405-
It is best to avoid trying to fit such models in MixedModels until
406-
the authors gain a better understanding of those cases."""
407-
end
417+
_distwarn(d)
408418

409419
LMM = LinearMixedModel(f, tbl; contrasts, wts, amalgamate)
410420
y = copy(LMM.y)

src/simulate.jl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,25 @@ Note that `n` is the `n` parameter for the Binomial distribution,
7676
random draw (an integer in [0, n]) into a probability (a float in [0,1]).
7777
"""
7878
function _rand(rng::AbstractRNG, ::Binomial, location, scale=missing, n=1)
79-
dist = Binomial(Int(n), location)
79+
dist = Binomial(Int(n), location)
8080
return rand(rng, dist) / n
8181
end
8282

8383
function _rand(rng::AbstractRNG, ::T, location, scale=missing, n=1) where T <: Union{Bernoulli,Poisson}
8484
dist = T(location)
8585
return rand(rng, dist)
86-
end
86+
end
87+
88+
function _rand(rng::AbstractRNG, ::Geometric, location, scale=missing, n=1)
89+
dist = Geometric(location)
90+
return rand(rng, dist)
91+
end
92+
93+
function _rand(rng::AbstractRNG, ::T, location, scale, n=1) where T <: Union{Gamma,InverseGaussian}
94+
@warn "Gamma and Inverse Gaussian are not supported in fitting and poorly tested in simulation" maxwarn=1
95+
dist = T(location, scale)
96+
return rand(rng, dist)
97+
end
8798

8899
function _rand(rng::AbstractRNG, ::Normal, location, scale=missing, n=1)
89100
# skip constructing a distribution
@@ -280,7 +291,8 @@ function _simulate!(
280291
# families with a dispersion parameter
281292
mul!(η, fullrankx(lm), β, one(T), one(T))
282293

283-
μ = resp === nothing ? linkinv.(Link(m), η) : GLM.updateμ!(resp, η).mu
294+
@info "" resp
295+
μ = isnothing(resp) ? GLM.linkfun.(Link(m), η) : GLM.updateμ!(resp, η).mu
284296

285297
# convert to the distribution / add in noise
286298
@inbounds for (idx, val) in enumerate(μ)

test/bootstrap.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,23 @@ end
6464
gm2sim = refit!(simulate!(StableRNG(42), deepcopy(gm2)); fast=true, progress=false)
6565
@test isapprox(gm2.β, gm2sim.β; atol=norm(stderror(gm2)))
6666
end
67+
68+
@testset "Geometric" begin
69+
n = 1000
70+
data = (; y=fill(1, n), g=rand('A':'G', n))
71+
data = (; y=rand(StableRNG(42), Geometric(0.5), n),
72+
g=rand('A':'G', n))
73+
@test_logs (:warn, r"geometric") MixedModel(@formula(y ~ 1 + (1|g)), data, Geometric())
74+
m = @suppress MixedModel(@formula(y ~ 1 + (1|g)), data, Geometric())
75+
v = simulate(StableRNG(42), m; β=[exp(0.5)], θ=[0])
76+
gmean = mean(rand(StableRNG(42), Geometric(), n))
77+
@test mean(v) gmean atol=0.005
78+
79+
simulate!(StableRNG(42), m; β=[exp(0.5)], θ=[0])
80+
v = response(m)
81+
@test mean(v) gmean atol=0.005
82+
end
83+
6784
@testset "_rand with dispersion" begin
6885
@test_throws ArgumentError MixedModels._rand(StableRNG(42), NegativeBinomial(), 1, 1)
6986

0 commit comments

Comments
 (0)