Skip to content

Commit

Permalink
YAS
Browse files Browse the repository at this point in the history
  • Loading branch information
palday committed Aug 19, 2023
1 parent 9a447a9 commit 1433b1e
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 29 deletions.
1 change: 1 addition & 0 deletions .github/workflows/YASG.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- 'src/**'
- 'test/**'
- 'docs/**'
- 'ext/**'
- '.github/workflows/YASG.yml'
- 'format/**'
jobs:
Expand Down
8 changes: 4 additions & 4 deletions ext/EffectsGLMExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ using StatsModels: TableRegressionModel
_link(m::TableRegressionModel{<:AbstractGLM}) = Link(m.model)
_link(m::AbstractGLM) = Link(m)

function Effects._difference_method!(eff::Vector{T}, err::Vector{T},
model::Union{TableRegressionModel{<:AbstractGLM}, AbstractGLM},
::AutoInvLink) where {T <: AbstractFloat}
function Effects._difference_method!(eff::Vector{T}, err::Vector{T},
model::Union{TableRegressionModel{<:AbstractGLM},
AbstractGLM},
::AutoInvLink) where {T<:AbstractFloat}
link = _link(model)
err .*= mueta.(link, eff)
eff .= linkinv.(link, eff)

return err
end


end # module
6 changes: 3 additions & 3 deletions ext/EffectsMixedModelsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ using Effects
using MixedModels
using GLM: Link, mueta, linkinv

function Effects._difference_method!(eff::Vector{T}, err::Vector{T},
model::GeneralizedLinearMixedModel,
::AutoInvLink) where {T <: AbstractFloat}
function Effects._difference_method!(eff::Vector{T}, err::Vector{T},
model::GeneralizedLinearMixedModel,
::AutoInvLink) where {T<:AbstractFloat}
link = Link(model)
err .*= mueta.(link, eff)
eff .= linkinv.(link, eff)
Expand Down
2 changes: 1 addition & 1 deletion format/run.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using JuliaFormatter
function main()
perfect = true
# note: keep in sync with `.github/workflows/format-check.yml`
for d in ["src/", "test/", "docs/"]
for d in ["src/", "ext/", "test/", "docs/"]
@info "...linting $d ..."
dir_perfect = format(d, YASStyle())
perfect = perfect && dir_perfect
Expand Down
15 changes: 7 additions & 8 deletions src/regressionmodel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,21 @@ end
# in addition to the difference method
# xref https://github.com/JuliaStats/GLM.jl/blob/c13577eaf3f418c58020534dd407532ee57f219b/src/glmfit.jl#L773-L783

function _difference_method!(eff::Vector{T}, err::Vector{T},
::RegressionModel,
invlink) where {T <: AbstractFloat}

function _difference_method!(eff::Vector{T}, err::Vector{T},
::RegressionModel,
invlink) where {T<:AbstractFloat}
err .*= ForwardDiff.derivative.(invlink, eff)
eff .= invlink.(eff)
return eff, err
end

function _difference_method!(::Vector{T}, ::Vector{T},
::RegressionModel,
::AutoInvLink) where {T <: AbstractFloat}
function _difference_method!(::Vector{T}, ::Vector{T},
::RegressionModel,
::AutoInvLink) where {T<:AbstractFloat}
@static if VERSION < v"1.9"
@error "AutoInvLink requires extensions and is thus not available on Julia < 1.9."
end
throw(ArgumentError("No appropriate extension is loaded for automatic " *
throw(ArgumentError("No appropriate extension is loaded for automatic " *
"determination of the inverse link for this model type"))
end

Expand Down
27 changes: 14 additions & 13 deletions test/delta_method.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ end
dat[!, :vol] = dat.Volunteer .== "yes"
model = glm(@formula(vol ~ Extraversion * Neuroticism), dat, Bernoulli())
design = Dict(:Extraversion => [13],
:Neuroticism => [16])
:Neuroticism => [16])
X = [1.0 13.0 16.0 13 * 16]
iv = Base.Fix1(GLM.linkinv, Link(model.model))
@static if VERSION >= v"1.9"
Expand All @@ -65,18 +65,18 @@ end

# compare with results from GLM.predict
pred = DataFrame(predict(model.model, X;
interval=:confidence,
interval_method=:delta,
level))
interval=:confidence,
interval_method=:delta,
level))
@test all(pred.prediction .≈ eff.vol)
@test all(isapprox.(pred.lower, eff.lower; atol=0.001))
@test all(isapprox.(pred.upper, eff.upper; atol=0.001))

eff_trans = effects(design, model; level)
transform!(eff_trans,
:vol => ByRow(iv),
:lower => ByRow(iv),
:upper => ByRow(iv); renamecols=false)
:vol => ByRow(iv),
:lower => ByRow(iv),
:upper => ByRow(iv); renamecols=false)
# for this model, things play out nicely
@test all(eff_trans.vol .≈ eff.vol)
@test all(isapprox.(eff_trans.lower, eff.lower; atol=0.001))
Expand All @@ -92,7 +92,8 @@ end
@test isapprox(only(eff_emm.upper), -0.292; atol=0.005)

# emmeans(model, ~ neuroticism * extraversion, level=0.68, transform="response")
eff_emm_trans = effects(Dict(:Extraversion => [12.4], :Neuroticism => [11.5]), model;
eff_emm_trans = effects(Dict(:Extraversion => [12.4], :Neuroticism => [11.5]),
model;
invlink)
@test isapprox(only(eff_emm_trans.vol), 0.414; atol=0.005)
@test isapprox(only(eff_emm_trans.err), 0.0133; atol=0.005)
Expand All @@ -103,13 +104,13 @@ end

@static if VERSION >= v"1.9"
@testset "link function in a MixedModel" begin
model = fit(MixedModel,
@formula(use ~ 1 + age + (1|urban)),
MixedModels.dataset(:contra),
model = fit(MixedModel,
@formula(use ~ 1 + age + (1 | urban)),
MixedModels.dataset(:contra),
Bernoulli(); progress=false)
design = Dict(:age => -10:10)
eff_manual = effects(design, model;
invlink=Base.Fix1(GLM.linkinv, Link(model)))
eff_manual = effects(design, model;
invlink=Base.Fix1(GLM.linkinv, Link(model)))
eff_auto = effects(design, model; invlink=AutoInvLink())

@test all(isapprox.(Matrix(eff_manual), Matrix(eff_auto)))
Expand Down

0 comments on commit 1433b1e

Please sign in to comment.