@@ -159,15 +159,21 @@ fit(
159
159
REML = REML,
160
160
)
161
161
162
- StatsBase. coef (m:: MixedModel ) = fixef (m, false )
162
+ function StatsBase. coef (m:: LinearMixedModel{T} ) where {T}
163
+ piv = fetrm (m). piv
164
+ invpermute! (fixef! (similar (piv, T), m), piv)
165
+ end
163
166
164
- βs (m:: LinearMixedModel ) = NamedTuple {(Symbol.(fixefnames (m))...,)} (( fixef (m) ... , ))
167
+ βs (m:: LinearMixedModel ) = NamedTuple {(Symbol.(coefnames (m))...,)} (coef (m ))
165
168
166
- StatsBase. coefnames (m:: LinearMixedModel ) = fixefnames (m, false )
169
+ function StatsBase. coefnames (m:: LinearMixedModel )
170
+ Xtrm = fetrm (m)
171
+ invpermute! (copy (Xtrm. cnames), Xtrm. piv)
172
+ end
167
173
168
- function StatsBase. coeftable (m:: MixedModel )
174
+ function StatsBase. coeftable (m:: LinearMixedModel )
169
175
co = coef (m)
170
- se = stderror ( m)
176
+ se = stderror! ( similar (co), m)
171
177
z = co ./ se
172
178
pvalue = ccdf .(Chisq (1 ), abs2 .(z))
173
179
names = coefnames (m)
@@ -285,13 +291,30 @@ function StatsBase.dof_residual(m::LinearMixedModel)::Int
285
291
n - m. optsum. REML * p
286
292
end
287
293
294
+ """
295
+ feind(m::MixedModel)
296
+
297
+ An internal utility to return the index in `m.allterms` of the fixed-effects term.
298
+ """
299
+ feind (m:: MixedModel ) = findfirst (Base. Fix2 (isa, FeMat), m. allterms)
300
+
288
301
"""
289
302
feL(m::MixedModel)
290
303
291
304
Return the lower Cholesky factor for the fixed-effects parameters, as an `LowerTriangular`
292
305
`p × p` matrix.
293
306
"""
294
- feL (m:: LinearMixedModel ) = LowerTriangular (m. L. blocks[end - 1 , end - 1 ])
307
+ function feL (m:: LinearMixedModel )
308
+ k = feind (m)
309
+ LowerTriangular (m. L. blocks[k, k])
310
+ end
311
+
312
+ """
313
+ fetrm(m::LinearMixedModel)
314
+
315
+ Return the fixed-effects term from `m.allterms`
316
+ """
317
+ fetrm (m) = m. allterms[feind (m)]
295
318
296
319
"""
297
320
fit!(m::LinearMixedModel[; verbose::Bool=false, REML::Bool=false])
344
367
345
368
function fitted! (v:: AbstractArray{T} , m:: LinearMixedModel{T} ) where {T}
346
369
# # FIXME : Create and use `effects(m) -> β, b` w/o calculating β twice
347
- vv = mul! (vec (v), first (m. feterms), fixef (m))
370
+ Xtrm = fetrm (m)
371
+ vv = mul! (vec (v), Xtrm, fixef! (similar (Xtrm. piv, T), m))
348
372
for (rt, bb) in zip (m. reterms, ranef (m))
349
373
unscaledre! (vv, rt, bb)
350
374
end
@@ -356,53 +380,44 @@ StatsBase.fitted(m::LinearMixedModel{T}) where {T} = fitted!(Vector{T}(undef, no
356
380
"""
357
381
fixef!(v::Vector{T}, m::LinearMixedModel{T})
358
382
359
- Overwrite `v` with the pivoted and, possibly, truncated fixed-effects coefficients of model `m`
360
- """
361
- fixef! (v:: AbstractVector{T} , m:: LinearMixedModel{T} ) where {T} =
362
- ldiv! (feL (m)' , copyto! (v, m. L. blocks[end , end - 1 ]))
383
+ Overwrite `v` with the pivoted fixed-effects coefficients of model `m`
363
384
385
+ For full-rank models the length of `v` must be the rank of `X`. For rank-deficient models
386
+ the length of `v` can be the rank of `X` or the number of columns of `X`. In the latter
387
+ case the calculated coefficients are padded with -0.0 out to the number of columns.
364
388
"""
365
- fixef(m::MixedModel, permuted=true)
366
-
367
- Return the fixed-effects parameter vector estimate of `m`.
368
-
369
- If `permuted` is `true` the vector elements are permuted according to
370
- `first(m.feterms).piv` and truncated to the rank of that term.
371
- """
372
- function fixef (m:: LinearMixedModel{T} , permuted = true ) where {T}
373
- val = ldiv! (feL (m)' , vec (copy (m. L. blocks[end , end - 1 ])))
374
- if ! permuted
375
- Xtrm = first (m. feterms)
376
- piv = Xtrm. piv
377
- p = length (piv)
378
- if Xtrm. rank < p
379
- val = copyto! (fill (- zero (T), p), val)
380
- end
381
- invpermute! (val, piv)
389
+ function fixef! (v:: AbstractVector{T} , m:: LinearMixedModel{T} ) where {T}
390
+ Xtrm = fetrm (m)
391
+ if isfullrank (Xtrm)
392
+ ldiv! (feL (m)' , copyto! (v, m. L. blocks[end , end - 1 ]))
393
+ else
394
+ ldiv! (
395
+ feL (m)' ,
396
+ view (copyto! (fill! (v, - zero (T)), m. L. blocks[end , end - 1 ]), 1 : (Xtrm. rank)),
397
+ )
382
398
end
383
- val
399
+ v
384
400
end
385
401
386
402
"""
387
- fixefnames (m::MixedModel, permuted=true )
403
+ fixef (m::MixedModel)
388
404
389
- Return the associated term names for fixed-effects parameter vector estimate of `m`.
405
+ Return the fixed-effects parameter vector estimate of `m`.
390
406
391
- If `permuted` is `true` the vector elements are permuted according to
392
- `first(m.feterms).piv` and truncated to the rank of that term.
407
+ In the rank-deficient case the truncated parameter vector, of length `rank(m)` is returned.
408
+ This is unlike `coef` which always returns a vector whose length matches the number of
409
+ columns in `X`.
393
410
"""
394
- function fixefnames (m:: LinearMixedModel{T} , permuted = true ) where {T}
395
- Xtrm = first (m. feterms)
396
- val = copy (Xtrm. cnames)
397
- if ! permuted
398
- piv = Xtrm. piv
399
- p = length (piv)
400
- invpermute! (val, piv)
401
- else
402
- val = val[1 : Xtrm. rank]
403
- end
411
+ fixef (m:: LinearMixedModel{T} ) where {T} = fixef! (Vector {T} (undef, fetrm (m). rank), m)
412
+
413
+ """
414
+ fixefnames(m::MixedModel)
404
415
405
- val
416
+ Return a (permuted and truncated in the rank-deficient case) vector of coefficient names.
417
+ """
418
+ function fixefnames (m:: LinearMixedModel{T} ) where {T}
419
+ Xtrm = fetrm (m)
420
+ Xtrm. cnames[1 : Xtrm. rank]
406
421
end
407
422
408
423
"""
@@ -788,6 +803,33 @@ function Statistics.std(m::LinearMixedModel)
788
803
isfinite (s) ? rmul! (push! (rl, [1.0 ]), s) : rl
789
804
end
790
805
806
+ """
807
+ stderror!(v::AbstractVector, m::LinearMixedModel)
808
+
809
+ Overwrite `v` with the standard errors of the fixed-effects coefficients in `m`
810
+
811
+ The length of `v` should be the total number of coefficients (i.e. `length(coef(m))`).
812
+ When the model matrix is rank-deficient the coefficients forced to `-0.0` have an
813
+ undefined (i.e. `NaN`) standard error.
814
+ """
815
+ function stderror! (v:: AbstractVector{T} , m:: LinearMixedModel{T} ) where {T}
816
+ L = feL (m)
817
+ scr = Vector {T} (undef, size (L, 2 ))
818
+ s = sdest (m)
819
+ fill! (v, zero (T) / zero (T)) # initialize to appropriate NaN for rank-deficient case
820
+ for i in eachindex (scr)
821
+ fill! (scr, false )
822
+ scr[i] = true
823
+ v[i] = s * norm (ldiv! (L, scr))
824
+ end
825
+ invpermute! (v, fetrm (m). piv)
826
+ v
827
+ end
828
+
829
+ function StatsBase. stderror (m:: LinearMixedModel{T} ) where {T}
830
+ stderror! (similar (fetrm (m). piv, T), m)
831
+ end
832
+
791
833
"""
792
834
updateA!(m::LinearMixedModel)
793
835
@@ -857,14 +899,15 @@ end
857
899
Returns the estimate of σ², the variance of the conditional distribution of Y given B.
858
900
"""
859
901
varest (m:: LinearMixedModel ) = pwrss (m) / dof_residual (m)
902
+
860
903
"""
861
904
vcov(m::LinearMixedModel)
862
905
863
906
Returns the variance-covariance matrix of the fixed effects.
864
907
If `corr=true`, then correlation of fixed effects is returned instead.
865
908
"""
866
909
function StatsBase. vcov (m:: LinearMixedModel{T} ; corr= false ) where {T}
867
- Xtrm = first (m . feterms )
910
+ Xtrm = fetrm (m )
868
911
iperm = invperm (Xtrm. piv)
869
912
p = length (iperm)
870
913
r = Xtrm. rank
@@ -880,7 +923,7 @@ function StatsBase.vcov(m::LinearMixedModel{T}; corr=false) where {T}
880
923
vv = covmat[iperm, iperm]
881
924
end
882
925
883
- corr ? StatsBase. cov2cor! (vv,stderror (m)) : vv
926
+ corr ? StatsBase. cov2cor! (vv, stderror (m)) : vv
884
927
end
885
928
886
929
"""
0 commit comments