Code
using AlgebraOfGraphics
using CairoMakie
using DataFrameMacros
using DataFrames
using EmbraceUncertainty: dataset
using LinearAlgebra
using MixedModels
using MixedModelsMakie
using Random
using RCall
using StandardizedPredictors
Load the packages to be used,
using AlgebraOfGraphics
using CairoMakie
using DataFrameMacros
using DataFrames
using EmbraceUncertainty: dataset
using LinearAlgebra
using MixedModels
using MixedModelsMakie
using Random
using RCall
using StandardizedPredictors
and declare some constants, if not already defined.
@isdefined(contrasts) || const contrasts = Dict{Symbol,Any}()
@isdefined(progress) || const progress = false
Longitudinal data consist of repeated measurements on the same subject, or some other observational unit, taken over time. Generally we wish to characterize the time trends within subjects and between subjects. The data will always include the response, the time covariate and the indicator of the subject on which the measurement has been made. If other covariates are recorded, say whether the subject is in the treatment group or the control group, we may wish to relate the within- and between-subject trends to such covariates.
In this chapter we introduce graphical and statistical techniques for the analysis of longitudinal data by applying them to a simple example.
Data from a dental study measuring the lengths of the ramus of the mandible (mm) in 20 boys at 8, 8.5, 9, and 9.5 years of age were reported in Elston & Grizzle (1962) and in Davis (2002). (Following the description in both of these references we will refer to these as measurements of the “ramus bone”, even though this is somewhat inaccurate.)
= dataset(:elstongrizzle) elstongrizzle
Arrow.Table with 80 rows, 3 columns, and schema:
:Subj String
:time Float64
:resp Float64
with metadata given by a Base.ImmutableDict{String, String} with 3 entries:
"title" => "Ramus bone lengths of boys from 8 to 9.5 years of age"
"references" => "@davis2002, Table 3.1, p. 52 and @elstongrizzle1962"
"sourcefile" => "EG.DAT"
Converting the table to a data frame provides the description
= DataFrame(elstongrizzle)
egdf describe(egdf)
Row | variable | mean | min | median | max | nmissing | eltype |
---|---|---|---|---|---|---|---|
Symbol | Union… | Any | Union… | Any | Int64 | DataType | |
1 | Subj | S01 | S20 | 0 | String | ||
2 | time | 8.75 | 8.0 | 8.75 | 9.5 | 0 | Float64 |
3 | resp | 50.0875 | 45.0 | 49.65 | 55.5 | 0 | Float64 |
A common way of plotting such longitudinal data is response versus time on a single axis with the observations for each individual joined by a line, Figure 3.1 (see also Figure 3.2, p. 52 of Davis (2002)).
draw(
data(egdf) *
mapping(
:time => "Age (yr)",
:resp => "Ramus bone length (mm)",
=:Subj,
color*
) visual(Scatter) + visual(Lines));
(=(; size=(600, 450)),
figure )
Unfortunately, unless there are very few subjects, such figures, sometimes called “spaghetti plots”, are difficult to decipher.
A preferred alternative is to plot response versus time with each subject’s data in a separate panel (Figure 3.2).
plot(
::xyplot(
lattice~ time|Subj,
resp $egdf,
type=c("g","p","r"),
aspect="xy",
index.cond=function(x,y) coef(lm(y ~ x)) %*% c(1,8),
xlab="Age (yr)",
ylab="Ramus bone length (mm)",
)
)NULL
To aid comparisons between subjects the axes are the same in every panel and the order of the panels is chosen systematically - in Figure 3.2 the order is by increasing bone length at 8 years of age. This ordering makes it easier to examine the patterns in the rate of increase versus the initial bone length.
And there doesn’t seem to be a strong relationship. Some subjects, e.g. S03
and S04
, with shorter initial bone lengths have low growth rates. Others, e.g. S10
and S20
, have low initial bone lengths and a high growth rate. Similarly, S06
and S11
have longer initial bone lengths and a low growth rate while S07
and S11
have longer initial bone lengths and a high growth rate.
Although it seems that there isn’t a strong correlation between initial bone length and growth rate in these data, a model with an overall linear trend and possibly correlated random effects for intercept and slope by subject estimates a strong negative correlation (-0.97) between these random effects.
= let f = @formula resp ~ 1 + time + (1 + time | Subj)
egm01 fit(MixedModel, f, egdf; contrasts, progress)
end
print(egm01)
Linear mixed model fit by maximum likelihood
resp ~ 1 + time + (1 + time | Subj)
logLik -2 logLik AIC AICc BIC
-117.2404 234.4809 246.4809 247.6316 260.7730
Variance components:
Column Variance Std.Dev. Corr.
Subj (Intercept) 90.339148 9.504691
time 1.162308 1.078104 -0.97
Residual 0.194449 0.440963
Number of obs: 80; levels of grouping factors: 20
Fixed-effects parameters:
─────────────────────────────────────────────────
Coef. Std. Error z Pr(>|z|)
─────────────────────────────────────────────────
(Intercept) 33.4975 2.26161 14.81 <1e-48
time 1.896 0.256697 7.39 <1e-12
─────────────────────────────────────────────────
The reason for this seemingly unlikely result is that the (Intercept)
term in the fixed effects and the random effects represents the bone length at age 0, which is not of interest here. Notice that the fixed-effects (Intercept)
estimate is about 33.5 mm, which is far below the observed range of the data (45.0 to 55.5 mm.)
Extrapolation from the observed range of ages, 8 years to 9.5 years, back to 0 years, will almost inevitably result is a negative correlation between slope and intercept.
A caterpillar plot of the random effects for intercept and slope, Figure 3.3, shows both the negative correlation between intercept and slope conditional means and wide prediction intervals on the random effects for the intercept.
caterpillar!(Figure(size=(600, 320)), ranefinfo(egm01, :Subj))
The problem of estimates of intercepts representing extrapolation beyond the observed range of the data is a common one for longitudinal data. If the time covariate represents an age, as it does here, or, say, a year in the range 2000 to 2020, the intercept, which corresponds to an age or year of zero, is rarely of interest.
The way to avoid extrapolation beyond the range of the data is to center the time covariate at an age or date that is of interest. For example, we may wish to consider “time in study” instead of age as the time covariate.
In discussing Figure 3.2 we referred to the bone length at 8 years of age, which was the time of first measurement for each of the subjects, as the “initial” bone length. If the purpose of the experiment is to create a predictive model for the growth rate that can be applied to boys who enter this age range then we could center the time at 8 years.
Alternatively, we could center at the average observed time, 8.75 years, or at some other value of interest.
The important thing is to make clear what the (Itercept)
parameter estimates represent. The StandardizedPredictors.jl package allows for convenient representations of several standardizing transformations in a contrasts
specification for the model. An advantage of this method of coding a transformation is that the coefficient names include a concise description of the transformation.
(In model specifications in R and later in Julia the name contrasts
has been come to be applied to ways of specifying the association between covariates in the data and parameters in a model. This is an extension of the original mathematical definition of contrasts amongst the levels of a categorical covariate.)
A model with time
centered at 8 years of age can be fit as
:time] = Center(8)
contrasts[= let f = @formula resp ~ 1 + time + (1 + time | Subj)
egm02 fit(MixedModel, f, egdf; contrasts, progress)
end
print(egm02)
Linear mixed model fit by maximum likelihood
resp ~ 1 + time(centered: 8) + (1 + time(centered: 8) | Subj)
logLik -2 logLik AIC AICc BIC
-117.2404 234.4809 246.4809 247.6316 260.7730
Variance components:
Column Variance Std.Dev. Corr.
Subj (Intercept) 6.096598 2.469129
time(centered: 8) 1.162325 1.078112 -0.23
Residual 0.194449 0.440964
Number of obs: 80; levels of grouping factors: 20
Fixed-effects parameters:
───────────────────────────────────────────────────────
Coef. Std. Error z Pr(>|z|)
───────────────────────────────────────────────────────
(Intercept) 48.6655 0.558243 87.18 <1e-99
time(centered: 8) 1.896 0.256699 7.39 <1e-12
───────────────────────────────────────────────────────
Comparing the parameter estimates from models egm01
and egm02
, we find that the only differences are in the estimates for the (Intercept)
terms in the fixed-effects parameters and the variance component parameters and in the correlation of the random effects. In terms of the predictions from the model and the likelihood at the parameter estimates, egm01
and egm02
are the same model.
A caterpillar plot, Figure 3.4, for egm02
shows much smaller spread and more precision in the distribution of the random effects for (Intercept)
but the same spread and precision for the time
random effects, although these random effects are displayed in a different order.
caterpillar!(Figure(size=(600, 380)), ranefinfo(egm02, :Subj))
A third option is to center the time
covariate at the mean of the original time
values.
:time] = Center()
contrasts[= let f = @formula resp ~ 1 + time + (1 + time | Subj)
egm03 fit(MixedModel, f, egdf; contrasts, progress)
end
print(egm03)
Linear mixed model fit by maximum likelihood
resp ~ 1 + time(centered: 8.75) + (1 + time(centered: 8.75) | Subj)
logLik -2 logLik AIC AICc BIC
-117.2404 234.4809 246.4809 247.6316 260.7730
Variance components:
Column Variance Std.Dev. Corr.
Subj (Intercept) 5.826541 2.413823
time(centered: 8.75) 1.162333 1.078116 +0.10
Residual 0.194448 0.440963
Number of obs: 80; levels of grouping factors: 20
Fixed-effects parameters:
──────────────────────────────────────────────────────────
Coef. Std. Error z Pr(>|z|)
──────────────────────────────────────────────────────────
(Intercept) 50.0875 0.541994 92.41 <1e-99
time(centered: 8.75) 1.896 0.256699 7.39 <1e-12
──────────────────────────────────────────────────────────
The default for the Center
contrast is to center about the mean and we write this contrasts
value as, simply, Center()
.
Notice that in this model the estimated correlation of the random effects for Subj
is positive.
One way of assessing a random-effects term in a linear mixed model is with a caterpillar plot, which shows two important characteristics, location and spread, of the conditional distribution \(({\mathcal{B}}|{\mathcal{Y}}={\mathbf{y}})\).
Another plot of interest is to show the extent to which the conditional means have been “shrunk” towards the origin by the mixed-model, which represents a compromise between fidelity to the data, measured by the sum of squared residuals, and simplicity of the model.
The model with the highest fidelity to the data corresponds to a fixed-effects model with the random effects model matrix, \({\mathbf{Z}}\), incorporated into the fixed-effects model matrix, \({\mathbf{X}}\). There are technical problems (rank deficiency) with trying to estimate parameters in this model but such “unconstrained” random effects can be approximated as the conditional means for a very large \({\boldsymbol{\Sigma}}\) matrix. (In practice we use a large multiple, say 1000, of the identity matrix as the value of \({\boldsymbol{\Sigma}}\).)
At the other end of the spectrum is the limit as \({\boldsymbol{\Sigma}}\rightarrow\mathbf{0}\), which is the simplest model, involving only the fixed-effects parameters, but usually with a comparatively poor fit.
A shrinkage plot shows the conditional means of the random effects from the model that was fit and those for a “large” \({\boldsymbol{\Sigma}}\).
shrinkageplot!(Figure(; size=(600, 600)), egm02)
Figure 3.5 reinforces some of the conclusions from Figure 3.4. In particular, the random effects for the (Intercept)
are reasonably precisely determined. We see this in Figure 3.4 because the intervals in the left panel are narrow. In Figure 3.5 there is little movement in the horizontal direction between the “unconstrained” within-subject estimates and the final random-effect locations.
As seen in Figure 3.2 some of the growth curves are reasonably straight (e.g. S03
, S11
, and S15
) whereas others are concave-up (e.g. S04
, S13
, and S17
) or concave-down (e.g. S05
, S07
, and S19
). One way of allowing for curvature in individual growth curves is to include a quadratic term for time
in both the fixed and random effects.
The usual cautions about polynomial terms in regression models apply even more emphatically to linear mixed models.
time
axis.time
values is very risky.For balanced data like egdf
we usually center the time
axis about the mean, producing
=
egm04 let f = @formula resp ~
1 + ctime + ctime^2 + (1 + ctime + ctime^2 | Subj)
= @transform(egdf, :ctime = :time - 8.75)
dat fit(MixedModel, f, dat; contrasts, progress)
end
print(egm04)
Linear mixed model fit by maximum likelihood
resp ~ 1 + ctime + :(ctime ^ 2) + (1 + ctime + :(ctime ^ 2) | Subj)
logLik -2 logLik AIC AICc BIC
-116.6187 233.2374 253.2374 256.4258 277.0577
Variance components:
Column Variance Std.Dev. Corr.
Subj (Intercept) 6.048884 2.459448
ctime 1.168085 1.080780 +0.08
ctime ^ 2 0.056758 0.238239 -0.62 +0.65
Residual 0.187159 0.432618
Number of obs: 80; levels of grouping factors: 20
Fixed-effects parameters:
────────────────────────────────────────────────
Coef. Std. Error z Pr(>|z|)
────────────────────────────────────────────────
(Intercept) 50.1 0.555373 90.21 <1e-99
ctime 1.896 0.256692 7.39 <1e-12
ctime ^ 2 -0.04 0.200673 -0.20 0.8420
────────────────────────────────────────────────
We see that the estimate for the population quadratic coefficient, -0.04, is small, relative to its standard error, 0.20, indicating that it is not significantly different from zero. This is not unexpected because some of the growth curves in Figure 3.2 are concave-up, while others are concave-down, and others don’t show a noticeable curvature.
A shrinkage plot, Figure 3.6, shows that the random effects for the quadratic term (vertical axis in the bottom row of panels) are highly attenuated relative to the unconstrained, “per-subject”, values.
shrinkageplot!(Figure(; size=(600, 600)), egm04)
Both of these results lead to the conclusion that linear growth, over the observed range of ages, should be adequate - a conclusion reinforced by a likelihood ratio test.
likelihoodratiotest(egm03, egm04) MixedModels.
model-dof | deviance | χ² | χ²-dof | P(>χ²) | |
resp ~ 1 + time(centered: 8.75) + (1 + time(centered: 8.75) | Subj) | 6 | 234 | |||
resp ~ 1 + ctime + :(ctime ^ 2) + (1 + ctime + :(ctime ^ 2) | Subj) | 10 | 233 | 1 | 4 | 0.8709 |
Often the “subjects” on which longitudinal measurements are made are divided into different treatment groups. Many of the examples cited in Davis (2002) are of this type, including one from Box (1950)
= dataset(:box) box1950
Arrow.Table with 135 rows, 4 columns, and schema:
:Group String
:Subj String
:time Int8
:resp Int16
with metadata given by a Base.ImmutableDict{String, String} with 3 entries:
"title" => "Body weight by week of rats in three treatment groups"
"references" => "@davis2002, Table 2.12, p. 32 and Problem 2.4, p. 32, and @b…
"sourcefile" => "BOX.DAT"
= DataFrame(box1950)
bxdf describe(bxdf)
Row | variable | mean | min | median | max | nmissing | eltype |
---|---|---|---|---|---|---|---|
Symbol | Union… | Any | Union… | Any | Int64 | DataType | |
1 | Group | Control | Thyroxin | 0 | String | ||
2 | Subj | S01 | S27 | 0 | String | ||
3 | time | 2.0 | 0 | 2.0 | 4 | 0 | Int8 |
4 | resp | 100.807 | 46 | 100.0 | 189 | 0 | Int16 |
There are three treatment groups
show(levels(bxdf.Group))
["Control", "Thioracil", "Thyroxin"]
and each “subject” (rat, in this case) is in only one of the treatment groups. This can be checked by comparing the number of unique Subj
levels to the number of unique combinations of Subj
and Group
.
nrow(unique(select(bxdf, :Group, :Subj))) ==
length(unique(bxdf.Subj))
true
Because the number of combinations of Subj
and Group
is equal to the number of subjects, each subject occurs in only one group.
These data are balanced with respect to time
(i.e. each rat is weighed at the same set of times) but not with respect to treatment, as can be seen by checking the number of rats in each treatment group.
combine(
groupby(unique(select(bxdf, :Group, :Subj)), :Group),
=> :n,
nrow )
Row | Group | n |
---|---|---|
String | Int64 | |
1 | Control | 10 |
2 | Thioracil | 10 |
3 | Thyroxin | 7 |
Considering first the control group, whose trajectories can be plotted in a “spaghetti plot”, Figure 3.7
=
bxaxes mapping(:time => "Time in trial (wk)", :resp => "Body weight (g)")
= groupby(bxdf, :Group)
bxgdf draw(
data(bxgdf[("Control",)]) *
*
bxaxes mapping(; color=:Subj) *
visual(Scatter) + visual(Lines));
(=(; size=(600, 450)),
figure )
or in separate panels ordered by initial weight, Figure 3.8.
let df = bxgdf[("Control",)]
draw(
data(df) *
*
bxaxes mapping(;
=:Subj =>
layoutsorter(sort!(filter(:time => iszero, df), :resp).Subj),
*
) visual(ScatterLines);
=(height=180, width=108),
axis
)end
The panels in Figure 3.8 show a strong linear trend with little evidence of systematic curvature.
A multi-panel plot for the Thioracil group, Figure 3.9,
let
= bxgdf[("Thioracil",)]
df draw(
data(df) *
*
bxaxes mapping(
=:Subj =>
layoutsorter(sort!(filter(:time => iszero, df), :resp).Subj),
*
) visual(ScatterLines);
=(height=180, width=108),
axis
)end
shows several animals (S18
, S19
, S21
, and S24
) whose rate of weight gain decreases as the trial goes on.
By contrast, in the Thyroxin group, Figure 3.10,
let
= bxgdf[("Thyroxin",)]
df draw(
data(df) *
*
bxaxes mapping(
=:Subj =>
layoutsorter(sort!(filter(:time => iszero, df), :resp).Subj),
*
) visual(ScatterLines);
=(height=180, width=108),
axis
)end
if there is any suggestion of curvature it would be concave-up.
Longitudinal data in which the observational units, each rat in this case, are in different treatment groups, require careful consideration of the origin on the time axis. If, as here, the origin on the time axis is when the treatments of the different groups began and the subjects have been randomly assigned to the treatment groups, we do not expect differences between groups at time zero.
Usually, when a model incorporates an effect for time
and a time & Group
interaction - checking for different underlying slopes of the response with respect to time
for each level of Group
, we will also include a “main effect” for Group
. This is sometimes called the hierarchical principle regarding interactions - a significant higher-order interaction usually forces inclusion of any lower-order interactions or main effects contained in it.
One occasion where the hierarchical principle does not apply is when the main effect for Group
would represent systematic differences in the response before the treatments began. Similarly in dose-response data; when a zero dose is included we could have a main effect for dose
and a dose & Group
interaction without a main effect for Group
, because zero dose of a treatment is the same as zero dose of a placebo.
We can begin with a main effect for Group
, as in
delete!(contrasts, :time)
=
bxm01 let f = @formula resp ~
1 + time + time^2) * Group + (1 + time + time^2 | Subj)
(fit(MixedModel, f, bxdf; contrasts, progress)
end
Est. | SE | z | p | σ_Subj | |
(Intercept) | 54.1086 | 1.5368 | 35.21 | <1e-99 | 4.0286 |
time | 24.0229 | 1.5639 | 15.36 | <1e-52 | 3.7538 |
time ^ 2 | 0.6143 | 0.3988 | 1.54 | 0.1235 | 0.9973 |
Group: Thioracil | 0.9086 | 2.1733 | 0.42 | 0.6759 | |
Group: Thyroxin | 0.6302 | 2.3949 | 0.26 | 0.7924 | |
time & Group: Thioracil | -1.6271 | 2.2116 | -0.74 | 0.4619 | |
time & Group: Thyroxin | -2.1861 | 2.4371 | -0.90 | 0.3697 | |
time ^ 2 & Group: Thioracil | -1.9357 | 0.5640 | -3.43 | 0.0006 | |
time ^ 2 & Group: Thyroxin | 0.7122 | 0.6215 | 1.15 | 0.2518 | |
Residual | 2.8879 |
but we expect that a model without the main effect for Group
,
=
bxm02 let f = @formula resp ~
1 + (time + time^2) & Group + (1 + time + time^2 | Subj)
fit(MixedModel, f, bxdf; contrasts, progress)
end
Est. | SE | z | p | σ_Subj | |
(Intercept) | 54.6085 | 0.9382 | 58.21 | <1e-99 | 4.0466 |
time & Group: Control | 24.1725 | 1.5206 | 15.90 | <1e-56 | |
time & Group: Thioracil | 22.2734 | 1.5206 | 14.65 | <1e-47 | |
time & Group: Thyroxin | 21.7977 | 1.8081 | 12.06 | <1e-32 | |
time ^ 2 & Group: Control | 0.5655 | 0.3806 | 1.49 | 0.1374 | |
time ^ 2 & Group: Thioracil | -1.2815 | 0.3806 | -3.37 | 0.0008 | |
time ^ 2 & Group: Thyroxin | 1.3393 | 0.4510 | 2.97 | 0.0030 | |
time | 3.7538 | ||||
time ^ 2 | 0.9977 | ||||
Residual | 2.8887 |
will be adequate, as confirmed by
likelihoodratiotest(bxm02, bxm01) MixedModels.
model-dof | deviance | χ² | χ²-dof | P(>χ²) | |
resp ~ 1 + time & Group + :(time ^ 2) & Group + (1 + time + :(time ^ 2) | Subj) | 14 | 836 | |||
resp ~ 1 + time + :(time ^ 2) + Group + time & Group + :(time ^ 2) & Group + (1 + time + :(time ^ 2) | Subj) | 16 | 835 | 0 | 2 | 0.9135 |
Unfortunately, the interpretations of some of the fixed-effects coefficients change between models bxm01
and bxm02
. In model bxm01
the coefficient labelled time
is the estimated slope at time zero for the Control
group. In model bxm02
this coefficient is labelled time & Group: Control
.
In model bxm01
the coefficient labelled time & Group: Thioracil
is the change in the estimated slope at time zero between the Thioracil
group and the Control
group. In model bxm02
the coefficient with this label is the estimated slope at time zero in the Thioracil
group.
Is there a way to write the formula for bxm02
to avoid this?
We see the effect of this changing interpretation in the p-values associated with these coefficients. In model bxm01
the only coefficients with low p-values are the (Intercept)
, the time
, representing a typical rate of weight gain in the control group at time zero, and the change in the quadratic term from the Control
group to the Thioracil
group.
A model without systematic differences between groups in the initial weight and the initial slope but with differences between groups in the quadratic coefficient is sensible. It would indicate that the groups are initially homogeneous both in weight and growth rate but, as the trial proceeds, the different treatments change the rate of growth.
=
bxm03 let f = @formula resp ~
1 + time + time^2 & Group + (1 + time + time^2 | Subj)
fit(MixedModel, f, bxdf; contrasts, progress)
end
Est. | SE | z | p | σ_Subj | |
(Intercept) | 54.6085 | 0.9349 | 58.41 | <1e-99 | 4.0129 |
time | 22.8534 | 0.9626 | 23.74 | <1e-99 | 3.8079 |
time ^ 2 & Group: Control | 0.7854 | 0.3240 | 2.42 | 0.0154 | |
time ^ 2 & Group: Thioracil | -1.3781 | 0.3240 | -4.25 | <1e-04 | |
time ^ 2 & Group: Thyroxin | 1.1630 | 0.3691 | 3.15 | 0.0016 | |
time ^ 2 | 0.9954 | ||||
Residual | 2.9094 |
likelihoodratiotest(bxm03, bxm02) MixedModels.
model-dof | deviance | χ² | χ²-dof | P(>χ²) | |
resp ~ 1 + time + :(time ^ 2) & Group + (1 + time + :(time ^ 2) | Subj) | 12 | 837 | |||
resp ~ 1 + time & Group + :(time ^ 2) & Group + (1 + time + :(time ^ 2) | Subj) | 14 | 836 | 1 | 2 | 0.5328 |
A caterpillar plot created from the conditional means and standard deviations of the random effects by Subj
for model bxm03
, Figure 3.11, indicates that all of the random-effects terms generate some prediction intervals that do not contain zero.
caterpillar!(Figure(; size=(600, 720)), bxm03)
A shrinkage plot, Figure 3.12
shrinkageplot!(Figure(; size=(600, 600)), bxm03)
shows that the random effects are considerably shrunk towards the origin, relative to the “unconstrained” values from within-subject fits, but none of the panels shows them collapsing to a line.
Nevertheless, the estimated unconditional distribution of the random effects in model bxm03
is a degenerate distribution.
That is, the estimated within-subject covariance of the random effects is singular.
issingular(bxm03)
true
One way to see this is because the relative covariance factor, \(\boldsymbol{\lambda}\), of the within-subject random effects is
Matrix(only(bxm03.λ))
3×3 Matrix{Float64}:
1.37931 0.0 0.0
1.15547 0.614804 0.0
-0.301045 0.162566 0.0
and we see that the third column is all zeros.
Thus, in a three-dimensional space the conditional means of the random effects for each rat, lie on a plane, even though each of the two-dimensional projections in Figure 3.12 show a scatter.
Three-dimensional plots of the conditional means of the random effects, Figure 3.13, can help to see that these points lie on a plane.
let
= Point3f.(eachcol(only(bxm03.b)))
bpts = Point3f.(eachcol(svd(only(bxm03.λ)).U))
Upts = Point3(zeros(Float32, 3))
origin = only(bxm03.reterms).cnames
xlabel, ylabel, zlabel = "time²"
zlabel = 0.5
perspectiveness = :data
aspect = Figure(; size=(600, 250))
f = -Upts[2] # second principle direction flipped to get positive w
u, v, w = asin(w)
elevation = atan(v, u)
azimuth =
ax1 Axis3(f[1, 1]; aspect, xlabel, ylabel, zlabel, perspectiveness)
= Axis3(
ax2 1, 2];
f[
aspect,
xlabel,
ylabel,
zlabel,
perspectiveness,
elevation,
azimuth,
)scatter!(ax1, bpts; marker='∘', markersize=20)
scatter!(ax2, bpts; marker='∘', markersize=20)
for p in Upts
= [origin, p]
seg lines!(ax1, seg)
lines!(ax2, seg)
end
fend
In each of the panels the three orthogonal lines from the origin are the three principle axes of the unconditional distribution of the random effects, corresponding to the columns of
svd(only(bxm03.λ)).U
3×3 Matrix{Float64}:
-0.723711 0.568469 0.39126
-0.675845 -0.698491 -0.235254
0.139557 -0.434687 0.889703
The panel on the right is oriented so the viewpoint is along the negative of the second principle axis, showing that there is considerable variation in the first principle direction and zero variation in the third principle direction.
We see that the distribution of the random effects in model bxm03
is degenerate but it is not clear how to simplify the model.
Coverage intervals from a parametric bootstrap sample for this model
= parametricbootstrap(
bxm03samp Xoshiro(8642468),
10_000,
bxm03;=false,
progress
)= DataFrame(bxm03samp.allpars)
bxm03pars DataFrame(shortestcovint(bxm03samp))
Row | type | group | names | lower | upper |
---|---|---|---|---|---|
String | String? | String? | Float64 | Float64 | |
1 | β | missing | (Intercept) | 52.731 | 56.421 |
2 | β | missing | time | 20.917 | 24.7162 |
3 | β | missing | time ^ 2 & Group: Control | 0.153234 | 1.43642 |
4 | β | missing | time ^ 2 & Group: Thioracil | -2.02241 | -0.724433 |
5 | β | missing | time ^ 2 & Group: Thyroxin | 0.423837 | 1.90148 |
6 | σ | Subj | (Intercept) | 2.47231 | 5.48025 |
7 | σ | Subj | time | 2.26442 | 5.44307 |
8 | ρ | Subj | (Intercept), time | 0.381022 | 1.0 |
9 | σ | Subj | time ^ 2 | 0.547204 | 1.39505 |
10 | ρ | Subj | (Intercept), time ^ 2 | -1.0 | -0.444921 |
11 | ρ | Subj | time, time ^ 2 | -0.898159 | -0.184577 |
12 | σ | residual | missing | 2.32503 | 3.27114 |
shows that the coverage intervals for both of the correlation parameters involving the (Intercept)
extend out to one of the limits of the allowable range [-1, 1] of correlations.
A kernel density plot, Figure 3.14, of the parametric bootstrap estimates of the correlation coefficients reinforces this conclusion.
draw(
data(@subset(bxm03pars, :type == "ρ")) *
mapping(
:value => "Bootstrap replicates of correlation estimates";
=(:names => "Variables"),
color*
) density();
AlgebraOfGraphics.=(; size=(600, 400)),
figure )
Even on the scale of Fisher’s z transformation, Figure 3.15, these estimates are highly skewed.
let
= @transform(
dat @subset(bxm03pars, :type == "ρ"),
:z = atanh(clamp(:value, -0.99999, 0.99999))
)= mapping(
mp :z => "Fisher's z transformation of correlation estimates";
=(:names => "Variables"),
color
)draw(
data(dat) * mp * AlgebraOfGraphics.density();
=(; size=(600, 400)),
figure
)end
Because of these high correlations, trying to deal with the degenerate random effects distribution by simply removing the random effects for time ^ 2
reduces the model too much.
=
bxm04 let f =
@formula resp ~ 1 + time + time^2 & Group + (1 + time | Subj)
fit(MixedModel, f, bxdf; contrasts, progress)
end
Est. | SE | z | p | σ_Subj | |
(Intercept) | 54.6085 | 1.2587 | 43.38 | <1e-99 | 5.5780 |
time | 22.8534 | 1.0454 | 21.86 | <1e-99 | 3.6245 |
time ^ 2 & Group: Control | 0.7633 | 0.2526 | 3.02 | 0.0025 | |
time ^ 2 & Group: Thioracil | -1.3807 | 0.2526 | -5.47 | <1e-07 | |
time ^ 2 & Group: Thyroxin | 1.1984 | 0.2890 | 4.15 | <1e-04 | |
Residual | 3.6290 |
likelihoodratiotest(bxm04, bxm03) MixedModels.
model-dof | deviance | χ² | χ²-dof | P(>χ²) | |
resp ~ 1 + time + :(time ^ 2) & Group + (1 + time | Subj) | 9 | 867 | |||
resp ~ 1 + time + :(time ^ 2) & Group + (1 + time + :(time ^ 2) | Subj) | 12 | 837 | 30 | 3 | <1e-05 |
as does eliminating within-subject correlations between the random-effects for the time^2
random effect and the other random effects.
=
bxm05 let f = @formula resp ~
1 +
+
time ^2 & Group +
time1 + time | Subj) +
(0 + time^2 | Subj)
(fit(MixedModel, f, bxdf; contrasts, progress)
end
Est. | SE | z | p | σ_Subj | |
(Intercept) | 54.6085 | 1.0433 | 52.34 | <1e-99 | 4.6060 |
time | 22.8534 | 0.8167 | 27.98 | <1e-99 | 2.5577 |
time ^ 2 & Group: Control | 0.8262 | 0.3471 | 2.38 | 0.0173 | |
time ^ 2 & Group: Thioracil | -1.4171 | 0.3471 | -4.08 | <1e-04 | |
time ^ 2 & Group: Thyroxin | 1.1605 | 0.4054 | 2.86 | 0.0042 | |
time ^ 2 | 0.9240 | ||||
Residual | 3.0374 |
likelihoodratiotest(bxm05, bxm03) MixedModels.
model-dof | deviance | χ² | χ²-dof | P(>χ²) | |
resp ~ 1 + time + :(time ^ 2) & Group + (1 + time | Subj) + (0 + :(time ^ 2) | Subj) | 10 | 850 | |||
resp ~ 1 + time + :(time ^ 2) & Group + (1 + time + :(time ^ 2) | Subj) | 12 | 837 | 13 | 2 | 0.0017 |
The three models bxm03
, bxm04
, and bxm05
have the same fixed-effects structure. The random effects specification varies from the most complicated (bxm03
), which produces a singular estimate of the covariance, to the simplest (bxm04
) structure to an intermediate structure (bxm05
).
The likelihood ratio tests give evidence for preferring bxm03
, the most complex of these models, but also one with a degenerate distribution of the random effects.
If we assume that the purpose of the experiment is to compare the effects of the two treatments versus the Control
group on the weight gain of the rats, then interest would focus on the fixed-effects parameters and, in particular, on those associated with the groups. The models give essentially the same predictions of weight versus time for a “typical” animal in each group, Figure 3.16.
let
= Float32.((0:256) / 64)
times = abs2.(times)
times² = zeros(Float32, 257)
z257 = hcat(
tmat ones(Float32, 257 * 3),
repeat(times, 3),
vcat(times², z257, z257),
vcat(z257, times², z257),
vcat(z257, z257, times²),
)= repeat(["Control", "Thioracil", "Thyroxin"]; inner=257)
grp draw(
data(
append!(
append!(
DataFrame(;
=tmat[:, 2],
times=tmat * Float32.(bxm03.beta),
wt=grp,
Group="bxm03",
model
),DataFrame(;
=tmat[:, 2],
times=tmat * Float32.(bxm04.beta),
wt=grp,
Group="bxm04",
model
),
),DataFrame(;
=tmat[:, 2],
times=tmat * Float32.(bxm05.beta),
wt=grp,
Group="bxm05",
model
),
),*
) mapping(
:times => "Time in trial (wk)",
:wt => "Weight (gm)";
=:Group,
color=:model,
col*
) visual(Lines);
=(width=120, height=130),
axis
)end
Other points to make:
1. Standard errors are different, largest for `bxm05`, smallest for `bxm04`
2. Real interest should center on the differences in the quadratic coef - trt vs control
3. Not sure how to code that up
4. More complex models require more iterations and more work per iteration
5. Probably go with `bxm03` in this case, even though it gives a degenerate dist'n of random effects. The idea is that the random effects are absorbing a form of rat-to-rat variability. The residual standard deviation does reflect this.
This page was rendered from git revision 93886a0 .