Skip to content

Commit 6007f57

Browse files
20260101 - GAM mixed model
1 parent e323c8d commit 6007f57

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

hlm.qmd

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ library("nlme")
2323
library("lmerTest")
2424
library("MASS")
2525
library("MCMCglmm")
26+
library("mgcv")
27+
library("parallelly")
2628
library("performance")
2729
library("ggplot2")
2830
```
@@ -74,6 +76,12 @@ mydata$ageMonthsCentered <- mydata$age - min(mydata$age, na.rm = TRUE)
7476
7577
mydata$ageYearsCentered <- mydata$ageMonthsCentered / 12
7678
mydata$ageYearsCenteredSquared <- mydata$ageYearsCentered ^ 2
79+
80+
mydata$sex <- factor(
81+
mydata$female,
82+
levels = c(0, 1),
83+
labels = c("male", "female")
84+
)
7785
```
7886

7987
# Estimator: ML or REML
@@ -533,6 +541,120 @@ summary(MCMCglmmModel)
533541

534542
# Nonlinear Mixed Models {#nonlinear}
535543

544+
## Generalized Additive Mixed Model {#gamm}
545+
546+
### Fit Model
547+
548+
```{r}
549+
#| label: parallel-cores-mixed-models
550+
#| include: false
551+
552+
num_cores <- parallelly::availableCores()
553+
num_true_cores <- parallelly::availableCores(logical = FALSE)
554+
```
555+
556+
```{r}
557+
#| eval: false
558+
559+
num_cores <- parallelly::availableCores() - 1
560+
num_true_cores <- parallelly::availableCores(logical = FALSE) - 1
561+
```
562+
563+
```{r}
564+
#| label: gam-mixed-models
565+
566+
gamModel <- mgcv::gam(
567+
math ~ s(ageYearsCentered, by = sex) + s(ageYearsCentered, id, bs = "fs"),
568+
data = mydata,
569+
nthreads = num_cores
570+
)
571+
572+
summary(gamModel)
573+
```
574+
575+
### Prototypical Growth Curve
576+
577+
```{r}
578+
newData <- expand.grid(
579+
female = c(0, 1),
580+
ageYears = seq(from = min(mydata$ageYears, na.rm = TRUE), to = max(mydata$ageYears, na.rm = TRUE), length.out = 10000))
581+
582+
newData$ageYearsCentered <- newData$ageYears - min(newData$ageYears)
583+
newData$ageYearsCenteredSquared <- newData$ageYearsCentered ^ 2
584+
585+
newData$sex <- NA
586+
newData$sex[which(newData$female == 0)] <- "male"
587+
newData$sex[which(newData$female == 1)] <- "female"
588+
newData$sex <- as.factor(newData$sex)
589+
590+
# add a dummy id
591+
newData$id <- mydata$id[1]
592+
593+
newData$predictedValue <- predict(
594+
gamModel,
595+
newdata = newData,
596+
exclude = "s(ageYearsCentered,id)"
597+
)
598+
599+
ggplot(
600+
newData,
601+
aes(
602+
x = ageYearsCentered,
603+
y = predictedValue,
604+
color = sex
605+
)
606+
) +
607+
geom_line(linewidth = 1.5) +
608+
labs(
609+
x = "Age (Centered)",
610+
y = "Math Score",
611+
color = "Sex"
612+
)
613+
```
614+
615+
### Individuals' Growth Curves
616+
617+
```{r}
618+
mydata$predictedValue <- predict(
619+
gamModel,
620+
newdata = mydata
621+
)
622+
623+
ggplot(
624+
data = mydata,
625+
mapping = aes(
626+
x = ageYears,
627+
y = predictedValue,
628+
group = factor(id))) +
629+
xlab("Age (Years)") +
630+
ylab("Math Score") +
631+
geom_line()
632+
```
633+
634+
##### Individuals' Trajectories Overlaid with Prototypical Trajectory
635+
636+
```{r}
637+
ggplot(
638+
data = mydata,
639+
mapping = aes(
640+
x = ageYears,
641+
y = predictedValue,
642+
group = factor(id))) +
643+
xlab("Age (Years)") +
644+
ylab("Math Score") +
645+
geom_line() +
646+
geom_line(
647+
data = newData,
648+
mapping = aes(
649+
x = ageYears,
650+
y = predictedValue,
651+
group = sex,
652+
color = sex),
653+
linewidth = 2)
654+
```
655+
656+
## Asymptotic Growth {#nonlinearAsymptotic}
657+
536658
```{r}
537659
nonlinearModel <- nlme(
538660
height ~ SSasymp(age, Asym, R0, lrc),

0 commit comments

Comments
 (0)