Skip to content

Commit 7b37191

Browse files
authored
added lmm and glmm as convenience wrappers for fit (#810)
* added lmm(...) as a wrapper/interface function for fit(LinearMixedModel, ...) * added test for lmm wrapper * added lmm to exports * added glmm as a convenience wrapper
1 parent bcd3e9f commit 7b37191

File tree

10 files changed

+101
-8
lines changed

10 files changed

+101
-8
lines changed

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
MixedModels v4.32.0 Release Notes
2+
==============================
3+
- Added `lmm` and `glmm` as convenience wrappers for `fit(LinearMixedModel, ...)` and `fit(GeneralizedLinearMixedModel, ...)` respectively [#810]
4+
15
MixedModels v4.31.0 Release Notes
26
==============================
37
- Added aliases `settheta!` and `profilesigma` for the functions `setθ!` and `profileσ` respectively
@@ -607,3 +611,4 @@ Package dependencies
607611
[#799]: https://github.com/JuliaStats/MixedModels.jl/issues/799
608612
[#801]: https://github.com/JuliaStats/MixedModels.jl/issues/801
609613
[#802]: https://github.com/JuliaStats/MixedModels.jl/issues/802
614+
[#810]: https://github.com/JuliaStats/MixedModels.jl/issues/810

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "MixedModels"
22
uuid = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316"
33
author = ["Phillip Alday <[email protected]>", "Douglas Bates <[email protected]>"]
4-
version = "4.31.0"
4+
version = "4.32.0"
55

66
[deps]
77
Arrow = "69666777-d1a9-59fb-9406-91d4454c9d45"

docs/src/api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ fit
3434
fit!
3535
fitted
3636
formula
37+
glmm
3738
isfitted
3839
islinear
3940
leverage
41+
lmm
4042
loglikelihood
4143
meanresponse
4244
modelmatrix

docs/src/constructors.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Model constructors
22

33
The `LinearMixedModel` type represents a linear mixed-effects model.
4-
Typically it is constructed from a `Formula` and an appropriate `Table` type, usually a `DataFrame`.
4+
Typically, it is constructed from a `Formula` and an appropriate `Table` type, usually a `DataFrame`.
55

66
## Examples of linear mixed-effects model fits
77

@@ -58,6 +58,15 @@ fm1 = fit(MixedModel, fm, dyestuff)
5858
DisplayAs.Text(ans) # hide
5959
```
6060

61+
You can also use the convenience function `lmm` to fit the model as follows:
62+
63+
```@example Main
64+
fm = @formula(yield ~ 1 + (1|batch))
65+
fm2 = lmm(fm, dyestuff)
66+
DisplayAs.Text(ans) # hide
67+
```
68+
Notice that both are equivalent.
69+
6170
(If you are new to Julia you may find that this first fit takes an unexpectedly long time, due to Just-In-Time (JIT) compilation of the code. The subsequent calls to such functions are much faster.)
6271

6372
```@example Main
@@ -210,14 +219,18 @@ DisplayAs.Text(ans) # hide
210219
## Fitting generalized linear mixed models
211220

212221
To create a GLMM representation, the distribution family for the response, and possibly the link function, must be specified.
222+
You can either use `fit(MixedModel, ...)` or `glmm(...)` to fit the model. For instance:
213223

214224
```@example Main
215225
verbagg = MixedModels.dataset(:verbagg)
216226
verbaggform = @formula(r2 ~ 1 + anger + gender + btype + situ + mode + (1|subj) + (1|item));
217227
gm1 = fit(MixedModel, verbaggform, verbagg, Bernoulli())
218228
DisplayAs.Text(ans) # hide
219229
```
220-
230+
The model can also be fit as
231+
```@example Main
232+
gm1 = glmm(verbaggform, verbagg, Bernoulli())
233+
```
221234
The canonical link, which is `LogitLink` for the `Bernoulli` distribution, is used if no explicit link is specified.
222235

223236
Note that, in keeping with convention in the [`GLM` package](https://github.com/JuliaStats/GLM.jl), the distribution family for a binary (i.e. 0/1) response is the `Bernoulli` distribution.

docs/src/index.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,36 @@ CurrentModule = MixedModels
77
*MixedModels.jl* is a Julia package providing capabilities for fitting and examining linear and generalized linear mixed-effect models.
88
It is similar in scope to the [*lme4*](https://github.com/lme4/lme4) package for `R`.
99

10+
# Quick Start
11+
12+
```@setup Main
13+
using DisplayAs
14+
```
15+
You can fit a model using a `lmer`-style model formula using `@formula` and a dataset.
16+
Here is a short example of how to fit a linear mixed-effects modeling using the `dyestuff` dataset:
17+
18+
```@example Main
19+
using DataFrames, MixedModels # load packages
20+
dyestuff = MixedModels.dataset(:dyestuff); # load dataset
21+
22+
lmod = lmm(@formula(yield ~ 1 + (1|batch)), dyestuff) # fit the model!
23+
DisplayAs.Text(ans) # hide
24+
```
25+
26+
For a generalized linear mixed-effect model, you have to specify a distribution for the response variable (and optionally a link function).
27+
A quick example of generalized linear model using the `verbagg` dataset:
28+
29+
```@example Main
30+
using DataFrames, MixedModels # load packages
31+
verbagg = MixedModels.dataset(:verbagg); # load dataset
32+
33+
frm = @formula(r2 ~ 1 + anger + gender + btype + situ + mode + (1|subj) + (1|item));
34+
bernmod = glmm(frm, verbagg, Bernoulli()) # fit the model!
35+
DisplayAs.Text(ans) # hide
36+
```
37+
38+
# Contents
39+
1040
```@contents
1141
Pages = [
1242
"constructors.md",

src/MixedModels.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,13 @@ export @formula,
105105
fulldummy,
106106
fnames,
107107
GHnorm,
108+
glmm,
108109
isfitted,
109110
islinear,
110111
issingular,
111112
leverage,
112113
levels,
114+
lmm,
113115
logdet,
114116
loglikelihood,
115117
lowerbd,

src/generalizedlinearmixedmodel.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,15 @@ function StatsAPI.fit(
190190
)
191191
end
192192

193+
"""
194+
glmm(args...; kwargs...)
195+
196+
Convenience wrapper for `fit(GeneralizedLinearMixedModel, args...; kwargs...)`.
197+
198+
See [`GeneralizedLinearMixedModel`](@ref) and [`fit!`](@ref) for more information.
199+
"""
200+
glmm(args...; kwargs...) = fit(GeneralizedLinearMixedModel, args...; kwargs...)
201+
193202
function StatsAPI.fit(
194203
::Type{MixedModel},
195204
f::FormulaTerm,

src/linearmixedmodel.jl

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,19 @@ function StatsAPI.fit(::Type{LinearMixedModel},
213213
σ=nothing,
214214
amalgamate=true,
215215
kwargs...)
216-
lmm = LinearMixedModel(f, tbl; contrasts, wts, σ, amalgamate)
217-
return fit!(lmm; kwargs...)
216+
lmod = LinearMixedModel(f, tbl; contrasts, wts, σ, amalgamate)
217+
return fit!(lmod; kwargs...)
218218
end
219219

220+
"""
221+
lmm(args...; kwargs...)
222+
223+
Convenience wrapper for `fit(LinearMixedModel, args...; kwargs...)`.
224+
225+
See [`LinearMixedModel`](@ref) and [`fit!`](@ref) for more information.
226+
"""
227+
lmm(args...; kwargs...) = fit(LinearMixedModel, args...; kwargs...)
228+
220229
function _offseterr()
221230
return throw(
222231
ArgumentError(

src/predict.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ function _predict(m::MixedModel{T}, newdata, β; new_re_levels) where {T}
119119
),
120120
)
121121
end
122-
lmm = LinearMixedModel(f, newdata; contrasts=contr)
122+
lmod = LinearMixedModel(f, newdata; contrasts=contr)
123123
ytemp =
124124
new_re_levels == :missing ? convert(Vector{Union{T,Missing}}, ytemp) : ytemp
125125

126-
ytemp, lmm
126+
ytemp, lmod
127127
end
128128

129129
pivotmatch = pivot(mnew)[pivot(m)]

test/fit.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,38 @@ using MixedModels
22
using Suppressor
33
using Test
44

5-
@testset "linear" begin
5+
@testset "linear, and lmm wrapper" begin
66
m1 = fit(MixedModel, @formula(yield ~ 1 + (1|batch)), MixedModels.dataset(:dyestuff); progress=false)
77
@test first(m1.θ) 0.7525806757718846 rtol=1.0e-5
8+
m2 = lmm(@formula(yield ~ 1 + (1|batch)), MixedModels.dataset(:dyestuff); progress=false)
9+
@test isa(m2, LinearMixedModel)
10+
@test first(m2.θ) 0.7525806757718846 rtol=1.0e-5
11+
@test deviance(m1) deviance(m2)
12+
@test isa(lmm(@formula(yield ~ 1 + (1|batch)), MixedModels.dataset(:dyestuff); progress=false, REML = true), LinearMixedModel)
13+
14+
# example from https://github.com/JuliaStats/MixedModels.jl/issues/194
15+
# copied from tetst/pls.jl
16+
data = (
17+
a = [1.55945122,0.004391538,0.005554163,-0.173029772,4.586284429,0.259493671,-0.091735715,5.546487603,0.457734831,-0.030169602],
18+
b = [0.24520519,0.080624178,0.228083467,0.2471453,0.398994279,0.037213859,0.102144973,0.241380251,0.206570975,0.15980803],
19+
c = PooledArray(["H","F","K","P","P","P","D","M","I","D"]),
20+
w1 = [20,40,35,12,29,25,65,105,30,75],
21+
w2 = [0.04587156,0.091743119,0.080275229,0.027522936,0.066513761,0.05733945,0.149082569,0.240825688,0.068807339,0.172018349],
22+
)
23+
m2 = lmm(@formula(a ~ 1 + b + (1|c)), data; wts = data.w1, progress=false)
24+
@test m2.θ [0.295181729258352] atol = 1.e-4
25+
@test stderror(m2) [0.9640167, 3.6309696] atol = 1.e-4
26+
@test vcov(m2) [0.9293282 -2.557527; -2.5575267 13.183940] atol = 1.e-4
827
end
928

1029
@testset "generalized" begin
1130
gm1 = fit(MixedModel, @formula(use ~ 1 + urban + livch + age + abs2(age) + (1|dist)),
1231
MixedModels.dataset(:contra), Bernoulli(); progress=false)
1332
@test deviance(gm1) 2372.7286 atol=1.0e-3
33+
34+
gm2 = glmm(@formula(use ~ 1 + urban + livch + age + abs2(age) + (1|dist)),
35+
MixedModels.dataset(:contra), Bernoulli(); progress=false)
36+
@test deviance(gm2) 2372.7286 atol=1.0e-3
1437
end
1538

1639
@testset "Normal-IdentityLink" begin

0 commit comments

Comments
 (0)