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
3 changes: 2 additions & 1 deletion src/MixedModelsExtras.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ using Tables

using MixedModels: replicate
using GLM: linkinv, Link
using MixedModels: replicate
using StatsModels: termnames, vif, gvif
export termnames, gvif, vif

StatsModels.termnames(::RandomEffectsTerm) = String[]

include("icc.jl")
export icc
export icc, confint

include("r2.jl")
export r², r2, adjr², adjr2
Expand Down
38 changes: 38 additions & 0 deletions src/icc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,41 @@ function _icc(tbl, groups::Union{Symbol,SymbolCollection}, σ²res)
σ² = σ²res .+ _group_var(tbl)
return σ²_α ./ σ²
end

function _icc_confint(values, level, method)
method in (:shortest, :equaltail) ||
throw(ArgumentError("`method` must be either :shortest or :equaltail."))
method === :shortest && return shortestcovint(values, level)
tails = ((1 - level) / 2, (1 + level) / 2)
return Tuple(quantile(values, tails))
end

"""
confint(boot::MixedModelBootstrap, groups; level::Real=0.95, method=:shortest)
confint(boot::MixedModelBootstrap, family, [groups]; level::Real=0.95, method=:shortest)

Compute a bootstrap confidence interval for the [`icc`](@ref) computed from `boot`.

The `groups` and `family` arguments are as for [`icc`](@ref).

The keyword argument `level` is the confidence level (0.95 by default). The keyword
argument `method` determines whether the `:shortest`, i.e. highest density, interval
is used (the default) or the `:equaltail`, i.e. quantile-based, interval is used --
matching the behavior of `confint(::MixedModelBootstrap)` from MixedModels.jl.
"""
function StatsBase.confint(boot::MixedModelBootstrap,
groups::Union{Symbol,SymbolCollection};
level::Real=0.95, method=:shortest)
return _icc_confint(icc(boot, groups), level, method)
end

function StatsBase.confint(boot::MixedModelBootstrap, family;
level::Real=0.95, method=:shortest)
return _icc_confint(icc(boot, family), level, method)
end

function StatsBase.confint(boot::MixedModelBootstrap, family,
groups::Union{Symbol,SymbolCollection};
level::Real=0.95, method=:shortest)
return _icc_confint(icc(boot, family, groups), level, method)
end
18 changes: 18 additions & 0 deletions test/icc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@
if row.iter == i; init=0.0)
for i in iters]
@test iccboot_subj ≈ σ²_subj_ref ./ (abs2.(boot.σ) .+ σ²_all_ref)

@testset "confint" begin
@test confint(boot, :subj) == shortestcovint(iccboot_subj)
@test confint(boot, :subj) == shortestcovint(iccboot_subj, 0.95)
@test confint(boot, :subj; level=0.8) == shortestcovint(iccboot_subj, 0.8)
@test confint(boot, [:subj, :item]) == shortestcovint(icc(boot))

lo, hi = confint(boot, :subj; method=:equaltail)
@test lo ≈ quantile(iccboot_subj, 0.025)
@test hi ≈ quantile(iccboot_subj, 0.975)

@test_throws ArgumentError confint(boot, :subj; method=:bogus)

# base MixedModels.jl `confint(::MixedModelBootstrap)` (no groups) is untouched
@test Tables.istable(confint(boot))
end
end
end

Expand Down Expand Up @@ -63,6 +79,8 @@ end
ci = shortestcovint(iccboot)
@test first(ci) < icc(modelbern) < last(ci)
@test iccboot ≈ icc(boot, Bernoulli(), Symbol("urban & dist"))
@test confint(boot, Bernoulli()) == ci
@test confint(boot, Bernoulli(), Symbol("urban & dist")) == ci
end
end

Expand Down
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ include("set_up_tests.jl")
Aqua.test_all(MixedModelsExtras; ambiguities=false,
piracies=(;
treat_as_own=[LinearMixedModel, MixedModel,
GeneralizedLinearMixedModel, RandomEffectsTerm]))
GeneralizedLinearMixedModel, RandomEffectsTerm,
MixedModelBootstrap]))
end

@testset "ICC" begin
Expand Down
Loading