Week 14

Repeated Measures

Author

Juan Steibel

Published

Invalid Date

[1] "C:/Users/jsteibel/OneDrive/Documents/job/500 ANS/2025/14"

Setup Code

#================================================================#
# Setup Options
#================================================================#

# good habit to run is the sessionInfo() function to print all relevant info
sessionInfo()
R version 4.4.2 (2024-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 10 x64 (build 19045)

Matrix products: default


locale:
[1] LC_COLLATE=English_United States.utf8 
[2] LC_CTYPE=English_United States.utf8   
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.utf8    

time zone: America/Chicago
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] htmlwidgets_1.6.4 compiler_4.4.2    fastmap_1.2.0     cli_3.6.3        
 [5] tools_4.4.2       htmltools_0.5.8.1 rstudioapi_0.17.1 yaml_2.3.10      
 [9] rmarkdown_2.29    knitr_1.49        jsonlite_1.8.9    xfun_0.49        
[13] digest_0.6.37     rlang_1.1.4       evaluate_1.0.1   
# remove all objects if restarting script
rm(list=ls())

knitr::opts_knit$set(root.dir = "C:/Users/jsteibel/OneDrive/Documents/job/500 ANS/2025/14/")
getwd()
[1] "C:/Users/jsteibel/OneDrive/Documents/job/500 ANS/2025/14"
# list all objects in your environment
ls()
character(0)
# set tibble width for printing - print all columns
options(tibble.width = Inf)

# remove scientific notation (by default will print)
options(scipen=999)

#================================================================#
# Packages
#================================================================#

# Here we must load the packages for the current environment to make them
# accessible. 

# load libraries
library(tidyverse)
library(tidymodels)
library(emmeans)
library(car)
library(DT)
library(gridExtra)
library(lme4)
library(lmerTest)
library(SASmixed)
library(mmrm)

Data input 1

First dataset: read weights from 30 rats over several weeks (days of age is the time variable)

workdir="C:/Users/jsteibel/OneDrive/Documents/job/500 ANS/2025/14/"
rats<-read.csv(paste0(workdir,"rats_rm.csv"))[,-1]
rats
   indiv d_8 d_15 d_22 d_29 d_36
1      1 151  199  246  283  320
2      2 145  199  249  293  354
3      3 147  214  263  312  328
4      4 155  200  237  272  297
5      5 135  188  230  280  323
6      6 159  210  252  298  331
7      7 141  189  231  275  305
8      8 159  201  248  297  338
9      9 177  236  285  350  376
10    10 134  182  220  260  296
11    11 160  208  261  313  352
12    12 143  188  220  273  314
13    13 154  200  244  289  325
14    14 171  221  270  326  358
15    15 163  216  242  281  312
16    16 160  207  248  288  324
17    17 142  187  234  280  316
18    18 156  203  243  283  317
19    19 157  212  259  307  336
20    20 152  203  246  286  321
21    21 154  205  253  298  334
22    22 139  190  225  267  302
23    23 146  191  229  272  302
24    24 157  211  250  285  323
25    25 132  185  237  286  331
26    26 160  207  257  303  345
27    27 169  216  261  295  333
28    28 157  205  248  289  316
29    29 137  180  219  258  291
30    30 153  200  244  286  324
glimpse(rats)
Rows: 30
Columns: 6
$ indiv <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1…
$ d_8   <int> 151, 145, 147, 155, 135, 159, 141, 159, 177, 134, 160, 143, 154,…
$ d_15  <int> 199, 199, 214, 200, 188, 210, 189, 201, 236, 182, 208, 188, 200,…
$ d_22  <int> 246, 249, 263, 237, 230, 252, 231, 248, 285, 220, 261, 220, 244,…
$ d_29  <int> 283, 293, 312, 272, 280, 298, 275, 297, 350, 260, 313, 273, 289,…
$ d_36  <int> 320, 354, 328, 297, 323, 331, 305, 338, 376, 296, 352, 314, 325,…
long_rats<-pivot_longer(data = rats,cols = d_8:d_36,names_to="days",names_prefix = "d_",values_to= "weight")
long_rats<-mutate(long_rats,indiv=as.factor(indiv),days=as.numeric(days))
long_rats
# A tibble: 150 × 3
   indiv  days weight
   <fct> <dbl>  <int>
 1 1         8    151
 2 1        15    199
 3 1        22    246
 4 1        29    283
 5 1        36    320
 6 2         8    145
 7 2        15    199
 8 2        22    249
 9 2        29    293
10 2        36    354
# ℹ 140 more rows

Represent the data

ggplot(long_rats,aes(x=days,y=weight,color=indiv))+geom_point()+geom_line()+geom_smooth(aes(color=NULL))
`geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Start fitting models

Saturated mean and variance model

long_rats<-mutate(long_rats,period=as.factor(days))
long_rats
# A tibble: 150 × 4
   indiv  days weight period
   <fct> <dbl>  <int> <fct> 
 1 1         8    151 8     
 2 1        15    199 15    
 3 1        22    246 22    
 4 1        29    283 29    
 5 1        36    320 36    
 6 2         8    145 8     
 7 2        15    199 15    
 8 2        22    249 22    
 9 2        29    293 29    
10 2        36    354 36    
# ℹ 140 more rows
fit_full<-mmrm(formula=weight~period-1+us(period|indiv),data = long_rats)
fit_full
mmrm fit

Formula:     weight ~ period - 1 + us(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  unstructured (15 variance parameters)
Inference:   REML
Deviance:    978.7812

Coefficients: 
 period8 period15 period22 period29 period36 
152.1667 201.7667 245.0333 289.5000 324.8000 

Model Inference Optimization:
Converged with code 0 and message: convergence: rel_reduction_of_f <= factr*epsmch
summary(fit_full)
mmrm fit

Formula:     weight ~ period - 1 + us(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  unstructured (15 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1008.8   1029.8   -489.4    978.8 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.038  29.027   74.68 <0.0000000000000002 ***
period15  201.767      2.313  29.030   87.24 <0.0000000000000002 ***
period22  245.033      2.805  29.039   87.36 <0.0000000000000002 ***
period29  289.500      3.496  29.043   82.81 <0.0000000000000002 ***
period36  324.800      3.551  29.042   91.46 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  124.5663 129.6434 141.3882 155.1270 133.5079
15 129.6434 160.4727 179.4888 204.6157 172.7079
22 141.3882 179.4888 236.0054 278.7911 256.4632
29 155.1270 204.6157 278.7911 366.6797 342.5501
36 133.5079 172.7079 256.4632 342.5501 378.3175
VarCorr(fit_full)
          8       15       22       29       36
8  124.5663 129.6434 141.3882 155.1270 133.5079
15 129.6434 160.4727 179.4888 204.6157 172.7079
22 141.3882 179.4888 236.0054 278.7911 256.4632
29 155.1270 204.6157 278.7911 366.6797 342.5501
36 133.5079 172.7079 256.4632 342.5501 378.3175
cov2cor(VarCorr(fit_full))
           8        15        22        29        36
8  1.0000000 0.9169581 0.8246165 0.7258446 0.6150049
15 0.9169581 1.0000000 0.9223075 0.8435189 0.7009441
22 0.8246165 0.9223075 1.0000000 0.9477078 0.8582935
29 0.7258446 0.8435189 0.9477078 1.0000000 0.9197132
36 0.6150049 0.7009441 0.8582935 0.9197132 1.0000000
#cov? #cor?


cr<-VarCorr(fit_full)

cr<-cr%>%as.tibble()%>%mutate(ID=rownames(cr))
Warning: `as.tibble()` was deprecated in tibble 2.0.0.
ℹ Please use `as_tibble()` instead.
ℹ The signature and semantics have changed, see `?as_tibble`.
(cr)
# A tibble: 5 × 6
    `8`  `15`  `22`  `29`  `36` ID   
  <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1  125.  130.  141.  155.  134. 8    
2  130.  160.  179.  205.  173. 15   
3  141.  179.  236.  279.  256. 22   
4  155.  205.  279.  367.  343. 29   
5  134.  173.  256.  343.  378. 36   
cr<-pivot_longer(cr,cols = 1:5,names_to="ID2",values_to= "cov")%>%mutate(ID=as.numeric(ID),ID2=as.numeric(ID2))

p1<-ggplot(cr,aes(ID,ID2,z=cov, ))+geom_contour()+stat_contour(geom="polygon",aes(fill=stat(level))) +
  scale_fill_distiller(palette = "Spectral", direction = -1)
print(p1)
Warning: `stat(level)` was deprecated in ggplot2 3.4.0.
ℹ Please use `after_stat(level)` instead.

Saturated mean and variance cs

fit_cs<-mmrm(formula=weight~period-1+cs(period|indiv),data = long_rats)
summary(fit_cs)
mmrm fit

Formula:     weight ~ period - 1 + cs(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  compound symmetry (2 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1096.5   1099.4   -546.3   1092.5 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.906  41.640   52.35 <0.0000000000000002 ***
period15  201.767      2.906  41.640   69.42 <0.0000000000000002 ***
period22  245.033      2.906  41.640   84.31 <0.0000000000000002 ***
period29  289.500      2.906  41.640   99.61 <0.0000000000000002 ***
period36  324.800      2.906  41.640  111.75 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  253.4262 199.6432 199.6432 199.6432 199.6432
15 199.6432 253.4262 199.6432 199.6432 199.6432
22 199.6432 199.6432 253.4262 199.6432 199.6432
29 199.6432 199.6432 199.6432 253.4262 199.6432
36 199.6432 199.6432 199.6432 199.6432 253.4262
cov2cor(VarCorr(fit_cs))
           8        15        22        29        36
8  1.0000000 0.7877765 0.7877765 0.7877765 0.7877765
15 0.7877765 1.0000000 0.7877765 0.7877765 0.7877765
22 0.7877765 0.7877765 1.0000000 0.7877765 0.7877765
29 0.7877765 0.7877765 0.7877765 1.0000000 0.7877765
36 0.7877765 0.7877765 0.7877765 0.7877765 1.0000000

Saturated mean and variance csh

fit_csh<-mmrm(formula=weight~period-1+csh(period|indiv),data = long_rats)
summary(fit_csh)
mmrm fit

Formula:     weight ~ period - 1 + csh(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  heterogeneous compound symmetry (6 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1067.0   1075.5   -527.5   1055.0 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.120  28.493   71.77 <0.0000000000000002 ***
period15  201.767      2.287  29.507   88.22 <0.0000000000000002 ***
period22  245.033      2.698  30.050   90.81 <0.0000000000000002 ***
period29  289.500      3.427  29.683   84.49 <0.0000000000000002 ***
period36  324.800      3.686  28.546   88.11 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  134.8775 120.6886 142.3932 180.8293 194.5291
15 120.6886 156.9040 153.5806 195.0366 209.8127
22 142.3932 153.5806 218.4135 230.1117 247.5452
29 180.8293 195.0366 230.1117 352.2400 314.3650
36 194.5291 209.8127 247.5452 314.3650 407.6339
cov2cor(VarCorr(fit_csh))
           8        15        22        29        36
8  1.0000000 0.8296208 0.8296208 0.8296208 0.8296208
15 0.8296208 1.0000000 0.8296208 0.8296208 0.8296208
22 0.8296208 0.8296208 1.0000000 0.8296208 0.8296208
29 0.8296208 0.8296208 0.8296208 1.0000000 0.8296208
36 0.8296208 0.8296208 0.8296208 0.8296208 1.0000000

Saturated mean and variance ante1

fit_ante1<-mmrm(formula=weight~period-1+adh(period|indiv),data = long_rats)
summary(fit_ante1)
mmrm fit

Formula:     weight ~ period - 1 + adh(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  heterogeneous ante-dependence (9 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1006.6   1019.2   -494.3    988.6 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.038  29.008   74.67 <0.0000000000000002 ***
period15  201.767      2.313  29.011   87.22 <0.0000000000000002 ***
period22  245.033      2.805  29.015   87.34 <0.0000000000000002 ***
period29  289.500      3.497  29.017   82.79 <0.0000000000000002 ***
period36  324.800      3.552  29.018   91.45 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  124.6022 129.6968 145.0788 171.3822 160.1093
15 129.6968 160.5460 179.5866 212.1464 198.1922
22 145.0788 179.5866 236.1208 278.9304 260.5834
29 171.3822 212.1464 278.9304 366.8300 342.7013
36 160.1093 198.1922 260.5834 342.7013 378.4567
cov2cor(VarCorr(fit_ante1))
           8        15        22        29        36
8  1.0000000 0.9169945 0.8458123 0.8016233 0.7373022
15 0.9169945 1.0000000 0.9223745 0.8741855 0.8040421
22 0.8458123 0.9223745 1.0000000 0.9477556 0.8717090
29 0.8016233 0.8741855 0.9477556 1.0000000 0.9197614
36 0.7373022 0.8040421 0.8717090 0.9197614 1.0000000

Saturated mean and variance toeplitz

fit_toep<-mmrm(formula=weight~period-1+toeph(period|indiv),data = long_rats)
Warning in mmrm(formula = weight ~ period - 1 + toeph(period | indiv), data =
long_rats): Divergence with optimizer L-BFGS-B due to problems: L-BFGS-B needs
finite values of 'fn'
summary(fit_toep)
mmrm fit

Formula:     weight ~ period - 1 + toeph(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  heterogeneous Toeplitz (9 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
   999.7   1012.3   -490.9    981.7 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.080  32.410   73.15 <0.0000000000000002 ***
period15  201.767      2.317  31.550   87.09 <0.0000000000000002 ***
period22  245.033      2.756  30.160   88.92 <0.0000000000000002 ***
period29  289.500      3.417  31.860   84.73 <0.0000000000000002 ***
period36  324.800      3.475  33.540   93.46 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  129.8289 133.7940 143.1982 150.0235 129.8438
15 133.7940 161.0305 177.2309 197.7460 169.9296
22 143.1982 177.2309 227.8123 261.3821 239.2124
29 150.0235 197.7460 261.3821 350.2523 329.6243
36 129.8438 169.9296 239.2124 329.6243 362.2962
cov2cor(VarCorr(fit_toep))
           8        15        22        29        36
8  1.0000000 0.9253303 0.8326513 0.7035309 0.5986920
15 0.9253303 1.0000000 0.9253303 0.8326513 0.7035309
22 0.8326513 0.9253303 1.0000000 0.9253303 0.8326513
29 0.7035309 0.8326513 0.9253303 1.0000000 0.9253303
36 0.5986920 0.7035309 0.8326513 0.9253303 1.0000000

Saturated mean and variance autoregressive heterogeneous

fit_ar1h<-mmrm(formula=weight~period-1+ar1h(period|indiv),data = long_rats)
summary(fit_ar1h)
mmrm fit

Formula:     weight ~ period - 1 + ar1h(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  heterogeneous auto-regressive order one (6 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1002.4   1010.8   -495.2    990.4 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.060  30.272   73.86 <0.0000000000000002 ***
period15  201.767      2.325  29.912   86.80 <0.0000000000000002 ***
period22  245.033      2.769  29.641   88.50 <0.0000000000000002 ***
period29  289.500      3.442  30.173   84.11 <0.0000000000000002 ***
period36  324.800      3.528  30.685   92.06 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  127.3458 133.0461 146.7499 168.9382 160.3436
15 133.0461 162.0991 178.7955 205.8290 195.3576
22 146.7499 178.7955 229.9818 264.7546 251.2854
29 168.9382 205.8290 264.7546 355.4306 337.3482
36 160.3436 195.3576 251.2854 337.3482 373.3904
cov2cor(VarCorr(fit_ar1h))
           8        15        22        29        36
8  1.0000000 0.9260180 0.8575093 0.7940691 0.7353223
15 0.9260180 1.0000000 0.9260180 0.8575093 0.7940691
22 0.8575093 0.9260180 1.0000000 0.9260180 0.8575093
29 0.7940691 0.8575093 0.9260180 1.0000000 0.9260180
36 0.7353223 0.7940691 0.8575093 0.9260180 1.0000000

model comparison

data.frame(model=c("UN","CS","CSH","ANTE"),
      AIC=round(c(AIC(fit_full),AIC(fit_cs),AIC(fit_csh),AIC(fit_ante1)),3),
      BIC=round(c(BIC(fit_full),BIC(fit_cs),BIC(fit_csh),BIC(fit_ante1)),3))
  model      AIC      BIC
1    UN 1008.781 1029.799
2    CS 1096.548 1099.351
3   CSH 1067.045 1075.452
4  ANTE 1006.587 1019.198
data.frame(model=c("UN","AR1H","TOEP","ANTE"),
      AIC=round(c(AIC(fit_full),AIC(fit_ar1h),AIC(fit_toep),AIC(fit_ante1)),3),
      BIC=round(c(BIC(fit_full),BIC(fit_ar1h),BIC(fit_toep),BIC(fit_ante1)),3))
  model      AIC      BIC
1    UN 1008.781 1029.799
2  AR1H 1002.381 1010.788
3  TOEP  999.736 1012.347
4  ANTE 1006.587 1019.198

Let’s test now the mean trend

fit_ante1<-mmrm(formula=weight~period+ar1h(period|indiv),data = long_rats)
summary(fit_ante1)
mmrm fit

Formula:     weight ~ period + ar1h(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  heterogeneous auto-regressive order one (6 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1002.4   1010.8   -495.2    990.4 

Coefficients: 
            Estimate Std. Error       df t value            Pr(>|t|)    
(Intercept) 152.1667     2.0603  30.2700   73.86 <0.0000000000000002 ***
period15     49.6000     0.8823  72.4200   56.22 <0.0000000000000002 ***
period22     92.8667     1.4586  62.6000   63.67 <0.0000000000000002 ***
period29    137.3333     2.1977  49.9100   62.49 <0.0000000000000002 ***
period36    172.6333     2.4498  47.2800   70.47 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  127.3458 133.0461 146.7499 168.9382 160.3436
15 133.0461 162.0991 178.7955 205.8290 195.3576
22 146.7499 178.7955 229.9818 264.7546 251.2854
29 168.9382 205.8290 264.7546 355.4306 337.3482
36 160.3436 195.3576 251.2854 337.3482 373.3904
emmeans(fit_ante1,specs = "period")
 period emmean   SE   df lower.CL upper.CL
 8         152 2.06 30.3      148      156
 15        202 2.32 29.9      197      207
 22        245 2.77 29.6      239      251
 29        290 3.44 30.2      282      297
 36        325 3.53 30.7      318      332

Confidence level used: 0.95 
emmeans(fit_ante1,specs = "period")%>%joint_tests() #this is the only way to do an ANOVA with mmrm
 model term df1   df2  F.ratio p.value
 period       4 47.28 1460.461  <.0001
Anova(fit_ante1)
Analysis of Fixed Effect Table (Type II F tests)
       Num Df Denom Df F Statistic               Pr(>=F)    
period      4   83.262      1460.5 < 0.00000000000000022 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
emmeans(fit_ante1,specs = "period")%>%pairs()
 contrast            estimate    SE   df t.ratio p.value
 period8 - period15     -49.6 0.882 72.4 -56.218  <.0001
 period8 - period22     -92.9 1.460 62.6 -63.667  <.0001
 period8 - period29    -137.3 2.200 49.9 -62.489  <.0001
 period8 - period36    -172.6 2.450 47.3 -70.468  <.0001
 period15 - period22    -43.3 1.070 60.8 -40.352  <.0001
 period15 - period29    -87.7 1.880 48.3 -46.702  <.0001
 period15 - period36   -123.0 2.200 46.5 -56.006  <.0001
 period22 - period29    -44.5 1.370 49.2 -32.574  <.0001
 period22 - period36    -79.8 1.830 49.5 -43.516  <.0001
 period29 - period36    -35.3 1.340 71.6 -26.281  <.0001

P value adjustment: tukey method for comparing a family of 5 estimates 
emmeans(fit_ante1,specs = "period")%>%contrast(.,method="consec")
 contrast            estimate    SE   df t.ratio p.value
 period15 - period8      49.6 0.882 72.4  56.218  <.0001
 period22 - period15     43.3 1.070 60.8  40.352  <.0001
 period29 - period22     44.5 1.370 49.2  32.574  <.0001
 period36 - period29     35.3 1.340 71.6  26.281  <.0001

P value adjustment: mvt method for 4 tests 
emmeans(fit_ante1,specs = "period")%>%contrast(.,method="poly")
 contrast  estimate   SE   df t.ratio p.value
 linear      433.00 6.46 49.8  67.068  <.0001
 quadratic   -27.40 3.59 99.5  -7.639  <.0001
 cubic        -2.83 2.44 60.1  -1.159  0.2508
 quartic     -17.90 5.09 95.7  -3.519  0.0007

Saturated mean and random coefficiets

long_rats<-mutate(long_rats,daysc=scale(days,center = T,scale = T),daysc2=daysc^2,daysc3=daysc^3)

long_rats
# A tibble: 150 × 7
   indiv  days weight period daysc[,1] daysc2[,1] daysc3[,1]
   <fct> <dbl>  <int> <fct>      <dbl>      <dbl>      <dbl>
 1 1         8    151 8         -1.41       1.99      -2.80 
 2 1        15    199 15        -0.705      0.497     -0.350
 3 1        22    246 22         0          0          0    
 4 1        29    283 29         0.705      0.497      0.350
 5 1        36    320 36         1.41       1.99       2.80 
 6 2         8    145 8         -1.41       1.99      -2.80 
 7 2        15    199 15        -0.705      0.497     -0.350
 8 2        22    249 22         0          0          0    
 9 2        29    293 29         0.705      0.497      0.350
10 2        36    354 36         1.41       1.99       2.80 
# ℹ 140 more rows
fit_poly0<-lmer(formula=weight~period-1+(1|indiv),data = long_rats)

fit_poly1<-lmer(formula=weight~period-1+(1+daysc|indiv),data = long_rats)
fit_icm1<-lmer(formula=weight~period-1+(1|indiv)+(daysc-1|indiv),data = long_rats)
fit_poly2<-lmer(formula=weight~period-1+(1+daysc+daysc2|indiv),data = long_rats)
fit_poly3<-lmer(formula=weight~period-1+(1+daysc+daysc2+daysc3|indiv),data = long_rats)
print(VarCorr(fit_poly0),comp="Variance")
 Groups   Name        Variance
 indiv    (Intercept) 199.643 
 Residual              53.783 
summary(fit_cs)
mmrm fit

Formula:     weight ~ period - 1 + cs(period | indiv)
Data:        long_rats (used 150 observations from 30 subjects with maximum 5 
timepoints)
Covariance:  compound symmetry (2 variance parameters)
Method:      Satterthwaite
Vcov Method: Asymptotic
Inference:   REML

Model selection criteria:
     AIC      BIC   logLik deviance 
  1096.5   1099.4   -546.3   1092.5 

Coefficients: 
         Estimate Std. Error      df t value            Pr(>|t|)    
period8   152.167      2.906  41.640   52.35 <0.0000000000000002 ***
period15  201.767      2.906  41.640   69.42 <0.0000000000000002 ***
period22  245.033      2.906  41.640   84.31 <0.0000000000000002 ***
period29  289.500      2.906  41.640   99.61 <0.0000000000000002 ***
period36  324.800      2.906  41.640  111.75 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Covariance estimate:
          8       15       22       29       36
8  253.4262 199.6432 199.6432 199.6432 199.6432
15 199.6432 253.4262 199.6432 199.6432 199.6432
22 199.6432 199.6432 253.4262 199.6432 199.6432
29 199.6432 199.6432 199.6432 253.4262 199.6432
36 199.6432 199.6432 199.6432 199.6432 253.4262
199.643 +53.783 
[1] 253.426
data.frame(model=c("RCM0","RCM1","ICM1","RCM2","RCM3"),
      AIC=round(c(AIC(fit_poly0),AIC(fit_poly1),AIC(fit_icm1),AIC(fit_poly2),AIC(fit_poly3)),3),
      BIC=round(c(BIC(fit_poly0),BIC(fit_poly1),BIC(fit_icm1),BIC(fit_poly2),BIC(fit_poly3)),3))
  model      AIC      BIC
1  RCM0 1106.548 1127.623
2  RCM1 1031.183 1058.279
3  ICM1 1041.051 1065.136
4  RCM2 1020.587 1056.715
5  RCM3 1015.622 1063.792
data.frame(model=c("UN","CS","CSH","ANTE"),
      AIC=round(c(AIC(fit_full),AIC(fit_cs),AIC(fit_csh),AIC(fit_ante1)),3),
      BIC=round(c(BIC(fit_full),BIC(fit_cs),BIC(fit_csh),BIC(fit_ante1)),3))
  model      AIC      BIC
1    UN 1008.781 1029.799
2    CS 1096.548 1099.351
3   CSH 1067.045 1075.452
4  ANTE 1002.381 1010.788

Compare CS models!

Data input 2

Second dataset: weights from 27 rats over several weeks, subject to three diets

library(nparLD)
Loading required package: MASS

Attaching package: 'MASS'
The following object is masked from 'package:dplyr':

    select
data(rat)
  glimpse(rat)
Rows: 135
Columns: 4
$ resp    <int> 46, 49, 49, 51, 52, 56, 57, 57, 60, 63, 52, 52, 54, 56, 57, 59…
$ time    <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ group   <fct> control, control, control, control, control, control, control,…
$ subject <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,…
  rat<-mutate(rat,period=as.factor(time),animal=as.factor(subject),resp=as.double(resp),trt=group)%>%dplyr::select(resp,time,animal,trt, period)
  glimpse(rat)
Rows: 135
Columns: 5
$ resp   <dbl> 46, 49, 49, 51, 52, 56, 57, 57, 60, 63, 52, 52, 54, 56, 57, 59,…
$ time   <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ animal <fct> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, …
$ trt    <fct> control, control, control, control, control, control, control, …
$ period <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
ggplot(rat,aes(x=time,y=resp,color=animal))+geom_point()+geom_line()+geom_smooth(aes(color=NULL))
`geom_smooth()` using method = 'loess' and formula = 'y ~ x'

ggplot(rat,aes(x=time,y=resp,group=animal,color=trt))+geom_point()+geom_line()+geom_smooth(aes(group=trt,color=trt),lwd=2)
`geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Compare models

First we run a models with different repeated measures structures

fit_cs<-mmrm(formula=resp~period*trt+cs(period|animal),data = rat)
fit_ar1<-mmrm(formula=resp~period*trt+ar1(period|animal),data = rat)
fit_csh<-mmrm(formula=resp~period*trt+csh(period|animal),data = rat)
fit_arh1<-mmrm(formula=resp~period*trt+ar1h(period|animal),data = rat)
fit_toep<-mmrm(formula=resp~period*trt+toeph(period|animal),data = rat)
Warning in mmrm(formula = resp ~ period * trt + toeph(period | animal), :
Divergence with optimizer L-BFGS-B due to problems: L-BFGS-B needs finite
values of 'fn'
fit_ante<-mmrm(formula=resp~period*trt+adh(period|animal),data = rat)
fit_un<-mmrm(formula=resp~period*trt+us(period|animal),data = rat)


data.frame(model=c("CS","AR1","CSH","ARH1","TOEP","ANTE","UN"),
      AIC=round(c(AIC(fit_cs),AIC(fit_ar1),AIC(fit_csh),AIC(fit_arh1),AIC(fit_toep),AIC(fit_ante),AIC(fit_un)),3),
      BIC=round(c(BIC(fit_cs),BIC(fit_ar1),BIC(fit_csh),BIC(fit_arh1),BIC(fit_toep),BIC(fit_ante),BIC(fit_un)),3))
  model     AIC     BIC
1    CS 901.113 903.705
2   AR1 823.634 826.226
3   CSH 850.132 857.907
4  ARH1 781.151 788.926
5  TOEP 771.296 782.959
6  ANTE 783.104 794.766
7    UN 768.100 787.538

Compare means

fit_un<-mmrm(formula=resp~period*trt+us(period|animal),data = rat)

Anova(fit_un,type="III")
Analysis of Fixed Effect Table (Type III F tests)
           Num Df Denom Df F Statistic               Pr(>=F)    
period          4       24      334.10 < 0.00000000000000022 ***
trt             2       24        7.73             0.0025559 ** 
period:trt      8       24        6.68             0.0001304 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
trt_at_time<-emmeans(fit_un,~trt|period)
time_at_trt<-emmeans(fit_un,~period|trt)

trt_at_time
period = 0:
 trt     emmean   SE df lower.CL upper.CL
 control   54.0 1.47 24     51.0     57.0
 thiour    54.7 1.47 24     51.7     57.7
 thyrox    55.6 1.76 24     51.9     59.2

period = 1:
 trt     emmean   SE df lower.CL upper.CL
 control   78.5 2.62 24     73.1     83.9
 thiour    76.3 2.62 24     70.9     81.7
 thyrox    75.9 3.13 24     69.4     82.3

period = 2:
 trt     emmean   SE df lower.CL upper.CL
 control  106.0 3.08 24     99.6    112.4
 thiour    95.8 3.08 24     89.4    102.2
 thyrox   104.9 3.68 24     97.3    112.5

period = 3:
 trt     emmean   SE df lower.CL upper.CL
 control  130.1 4.26 24    121.3    138.9
 thiour   108.2 4.26 24     99.4    117.0
 thyrox   134.1 5.09 24    123.6    144.7

period = 4:
 trt     emmean   SE df lower.CL upper.CL
 control  160.6 5.18 24    149.9    171.3
 thiour   124.0 5.18 24    113.3    134.7
 thyrox   164.3 6.19 24    151.5    177.1

Confidence level used: 0.95 
trt_at_time%>%pairs()
period = 0:
 contrast         estimate   SE df t.ratio p.value
 control - thiour   -0.700 2.08 24  -0.337  0.9395
 control - thyrox   -1.571 2.29 24  -0.686  0.7735
 thiour - thyrox    -0.871 2.29 24  -0.381  0.9235

period = 1:
 contrast         estimate   SE df t.ratio p.value
 control - thiour    2.200 3.71 24   0.593  0.8250
 control - thyrox    2.643 4.09 24   0.647  0.7959
 thiour - thyrox     0.443 4.09 24   0.108  0.9935

period = 2:
 contrast         estimate   SE df t.ratio p.value
 control - thiour   10.200 4.35 24   2.343  0.0688
 control - thyrox    1.143 4.80 24   0.238  0.9692
 thiour - thyrox    -9.057 4.80 24  -1.888  0.1639

period = 3:
 contrast         estimate   SE df t.ratio p.value
 control - thiour   21.900 6.03 24   3.634  0.0036
 control - thyrox   -4.043 6.64 24  -0.609  0.8167
 thiour - thyrox   -25.943 6.64 24  -3.907  0.0019

period = 4:
 contrast         estimate   SE df t.ratio p.value
 control - thiour   36.600 7.33 24   4.995  0.0001
 control - thyrox   -3.686 8.07 24  -0.457  0.8920
 thiour - thyrox   -40.286 8.07 24  -4.990  0.0001

P value adjustment: tukey method for comparing a family of 3 estimates 
trt_at_time%>%plot()
Error in ggplot2::theme_light(base_size = base_size, base_family = base_family, : unused arguments (header_family = header_family, ink = ink, paper = paper, accent = accent)
time_at_trt
trt = control:
 period emmean   SE df lower.CL upper.CL
 0        54.0 1.47 24     51.0     57.0
 1        78.5 2.62 24     73.1     83.9
 2       106.0 3.08 24     99.6    112.4
 3       130.1 4.26 24    121.3    138.9
 4       160.6 5.18 24    149.9    171.3

trt = thiour:
 period emmean   SE df lower.CL upper.CL
 0        54.7 1.47 24     51.7     57.7
 1        76.3 2.62 24     70.9     81.7
 2        95.8 3.08 24     89.4    102.2
 3       108.2 4.26 24     99.4    117.0
 4       124.0 5.18 24    113.3    134.7

trt = thyrox:
 period emmean   SE df lower.CL upper.CL
 0        55.6 1.76 24     51.9     59.2
 1        75.9 3.13 24     69.4     82.3
 2       104.9 3.68 24     97.3    112.5
 3       134.1 5.09 24    123.6    144.7
 4       164.3 6.19 24    151.5    177.1

Confidence level used: 0.95 
time_at_trt%>%plot()
Error in ggplot2::theme_light(base_size = base_size, base_family = base_family, : unused arguments (header_family = header_family, ink = ink, paper = paper, accent = accent)
time_at_trt%>%contrast(.,method="poly")
trt = control:
 contrast  estimate    SE df t.ratio p.value
 linear      264.80 13.00 24  20.307  <.0001
 quadratic     8.60  5.62 24   1.529  0.1393
 cubic         3.40  3.30 24   1.030  0.3132
 quartic      16.20  4.05 24   4.001  0.0005

trt = thiour:
 contrast  estimate    SE df t.ratio p.value
 linear      170.50 13.00 24  13.075  <.0001
 quadratic   -18.70  5.62 24  -3.325  0.0028
 cubic         5.50  3.30 24   1.667  0.1086
 quartic      15.50  4.05 24   3.828  0.0008

trt = thyrox:
 contrast  estimate    SE df t.ratio p.value
 linear      275.71 15.60 24  17.690  <.0001
 quadratic    20.00  6.72 24   2.975  0.0066
 cubic        -7.86  3.94 24  -1.992  0.0579
 quartic       9.00  4.84 24   1.860  0.0752