%\VignetteIndexEntry{LMMstar: overview}
%\VignetteEngine{R.rsp::asis}
%\VignetteKeyword{PDF}
%\VignetteKeyword{vignette}
%\VignetteKeyword{package}

## chunk 2
library(LMMstar)

## chunk 3
utils::packageVersion("LMMstar")

## chunk 4
library(ggplot2) ## autoplot method
library(nlme) ## ranef method
library(lava) ## iid, information, manifest methods

## * Illustrative dataset

## chunk 5
data(gastricbypassL, package = "LMMstar")
head(gastricbypassL)

## chunk 6
gastricbypassL$group <- as.factor(as.numeric(gastricbypassL$id)%%2)

## chunk 7
gastricbypassL$baseline <- gastricbypassL$time<0

## chunk 8
data(gastricbypassW, package = "LMMstar")
head(gastricbypassW)

## chunk 9
gastricbypassW$group <- as.numeric(gastricbypassW$id)%%2

## chunk 10
gastricbypassL.NNA <- gastricbypassL[!is.na(gastricbypassL$glucagonAUC),]

## * Visualization & descriptive statistics
## ** Graphical display

## chunk 11
scatterplot(gastricbypassW, ## left panel
            columns = c("weight1","weight2","weight3","weight4")) 

## chunk 12
scatterplot(weight~time|id, data = gastricbypassL, ## right panel
            type.diag = "hist", group = "group")

## chunk 14
gg.spa <- ggplot(gastricbypassL, aes(x=time,y=weight,group=id,color=id))
gg.spa <- gg.spa + geom_point() + geom_line()
gg.spa

## ** Missing data patterns

## chunk 15
mp <- summarizeNA(gastricbypassL)
mp

## chunk 16
plot(mp)

## ** Summary statistics

## chunk 18
sss <- summarize(weight+glucagonAUC ~ time, data = gastricbypassL, na.rm = TRUE)
print(sss, digits = 3)

## chunk 19
sss2 <- summarize(weight ~ time|id, data = gastricbypassL, na.rm = TRUE)
print(sss2, digits = 3)

## chunk 20
plot(sss2, type = "mean") ## left panel
plot(sss2, type = "sd") ## middle panel
plot(sss2, type = "cor") ## right panel

## ** Correlation and partial correlations

## chunk 22
partialCor(weight + glucagonAUC ~ 1, by = "group", data = gastricbypassL)

## chunk 23
gastricbypassL.0 <- gastricbypassL[gastricbypassL$group==0,]
rho <- cor.test(gastricbypassL.0$weight, gastricbypassL.0$glucagonAUC)
c(rho$estimate, p.value = rho$p.value)

## chunk 24
partialCor(weight + glucagonAUC ~ 1, by = "group", effects = "Dunnett",
           data = gastricbypassL)

## chunk 25
partialCor(weight4 + glucagonAUC4 ~ weight1,
           data = gastricbypassW)

## chunk 26
partialCor(list(weight1 ~ glucagonAUC1, weight4 ~ glucagonAUC4),
           data = gastricbypassW)

## * Multiple Student's t-tests

## chunk 27
restt <- t.test(weight1 ~ group, data = gastricbypassW)
c(estimate = unname(diff(restt$estimate)), p.value = restt$p.value)

## chunk 28
## single step max-test adjustment (see help(confint.Wald_lmm) for details)
mt.test(weight1+weight2+weight3+weight4~group, data = gastricbypassW)

## chunk 29
## no adjustment
mt.test(weight1+weight2+weight3+weight4~group, data = gastricbypassW, method = "none")

## chunk 30
## bonferroni adjustment
mt.test(weight1+weight2+weight3+weight4~group, data = gastricbypassW, method = "bonferroni")

## * Linear mixed model (LMM)
## ** Classical covariance patterns

## chunk 31
eId.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id, 
               structure = "ID", data = gastricbypassL)
eId.lmm
cat(" modeled residual variance-covariance: \n");sigma(eId.lmm)

## chunk 32
eInd.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id, 
                structure = "IND", data = gastricbypassL)
eInd.lmm
cat(" modeled residual variance-covariance: \n");sigma(eInd.lmm)

## chunk 33
eCS.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
               structure = "CS", data = gastricbypassL)
eCS.lmm
cat(" modeled residual variance-covariance: \n");sigma(eCS.lmm)

## chunk 34
eTOE.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
                structure = "TOEPLITZ", data = gastricbypassL)
eTOE.lmm
cat(" modeled residual correlation: \n");cov2cor(sigma(eTOE.lmm))

## chunk 35
eUN.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
               structure = "UN", data = gastricbypassL)
eUN.lmm
cat(" modeled residual variance-covariance: \n");sigma(eUN.lmm)

## chunk 36
eSCS.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
                structure = CS(group~1), data = gastricbypassL)
eSCS.lmm

## chunk 37
eSUN.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
                structure = UN(group~1), data = gastricbypassL)
eSUN.lmm

## chunk 38
sigma(eSCS.lmm)

## chunk 39
sigma(eSUN.lmm)

## chunk 40
eBCS.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
                structure = CS(~baseline, type = "homogeneous"), data = gastricbypassL)
eBCS.lmm
cat(" modeled residual variance-covariance: \n");sigma(eBCS.lmm)

## chunk 42
eBUN.lmm <- lmm(glucagonAUC ~ visit*group, repetition = ~time|id,
                structure = CS(~baseline, type = "heterogeneous"), data = gastricbypassL)
eBUN.lmm
cat(" modeled residual variance-covariance: \n");sigma(eBUN.lmm)

## ** User-specific covariance patterns

## chunk 43
rho.2block <- function(p,n.time,X){
  rho <- matrix(1, nrow = n.time, ncol = n.time)
  rho[1,2] <- rho[2,1] <- rho[4,5] <- rho[5,4] <- p["rho1"]
  rho[1,3] <- rho[3,1] <- rho[4,6] <- rho[6,4] <- p["rho2"]
  rho[2,3] <- rho[3,2] <- rho[5,6] <- rho[6,5] <- p["rho3"]
  rho[4:6,1:3] <- rho[1:3,4:6] <- p["rho4"]
  return(rho)
}
Rho <- rho.2block(p = c(rho1=0.25,rho2=0.5,rho3=0.4,rho4=0.1),
                  n.time = 6)
Rho

## chunk 44
set.seed(11)
Y <- mvtnorm::rmvnorm(1000, mean = rep(0,6), sigma = Rho)
dfW <- cbind(id = 1:NROW(Y), as.data.frame(Y))
dfL <- reshape2::melt(dfW, id.vars = "id", variable.name = "time")
dfL[dfL$id %in% 1:2,]

## chunk 45
dfL[dfL$id==1,]

## chunk 46
dfL[dfL$id==2,]

## chunk 47
myStruct <- CUSTOM(~time,
                   FCT.sigma = function(p,n.time,X){rep(p,n.time)}, ## function f
                   init.sigma = c("sigma"=1),
                   FCT.rho = rho.2block, ## function g
                   init.rho = c("rho1"=0.25,"rho2"=0.25,"rho3"=0.25,"rho4"=0.25))

## chunk 48
e.lmmCUSTOM <- lmm(value~time, repetition=~time|id,
                   structure = myStruct, data=dfL,
                   df = FALSE) ## df = FALSE to save computation time
logLik(e.lmmCUSTOM)

## chunk 49
cov2cor(sigma(e.lmmCUSTOM))

## chunk 50
system.time(
  e.lmmDEFAULT.CS <- lmm(value~time, repetition = ~time|id,
                         structure = "CS", data = dfL,
                         df = FALSE)
)

## chunk 51
myCS <- CUSTOM(~1,
               FCT.sigma = function(p,n.time,X){rep(p,n.time)},
               init.sigma = c("sigma"=1), 
               FCT.rho = function(p,n.time,X){p+diag(1-p,n.time,n.time)},
               init.rho = c("rho"=0.5))

## chunk 52
system.time(
  e.lmmCUSTOM.CS <- lmm(value~time, repetition = ~time|id,
                        structure = myCS, data = dfL,
                        df = FALSE)
)

## chunk 53
logLik(e.lmmDEFAULT.CS)
logLik(e.lmmCUSTOM.CS)

## chunk 54
e.lmmDEFAULT.CS$opt$n.iter
e.lmmCUSTOM.CS$opt$n.iter

## chunk 55
myCS.wD <- CUSTOM(~1,
                  FCT.sigma = function(p,n.time,X){rep(p,n.time)},
                  dFCT.sigma = function(p,n.time,X){list(sigma = rep(1,n.time))},
                  d2FCT.sigma = function(p,n.time,X){list(sigma = rep(0,n.time))},
                  init.sigma = c("sigma"=1),
                  FCT.rho = function(p,n.time,X){p+diag(1-p,n.time,n.time)},
                  dFCT.rho = function(p,n.time,X){list(rho = 1-diag(1,n.time,n.time))},
                  d2FCT.rho = function(p,n.time,X){list(rho = matrix(0,n.time,n.time))},
                  init.rho = c("rho"=0.5))

## chunk 56
system.time(
  e.lmmCUSTOMwD.CS <- lmm(value~time,
                          repetition = ~time|id,
                          structure = myCS.wD, 
                          data = dfL, df = FALSE
                          )
)

## ** Estimation procedure

## chunk 57
eCS.lmm.bis <- update(eCS.lmm, control = list(trace = 2))

## chunk 58
init.all <- coef(eCS.lmm, effects = "all")
eCS.lmm.bis <- update(eCS.lmm, control = list(init = init.all, trace = 1))

## chunk 59
init.mean <- coef(eCS.lmm, effects = "mean")
eCS.lmm.bis <- update(eCS.lmm, control = list(init = init.mean, trace = 2))

## chunk 60
init.vcov <- sigma(eCS.lmm)
eCS.lmm.bis <- update(eCS.lmm, control = list(init = init.vcov, trace = 1))

## ** Model output

## chunk 61
summary(eUN.lmm)

## chunk 62
summary(eUN.lmm, hide.mean = TRUE)

## chunk 63
oo <- capture.output(summary(eUN.lmm, hide.fit = TRUE, hide.data = TRUE, hide.cor = TRUE, hide.var = TRUE, hide.sd = TRUE))
cat(sapply(oo[-(1:2)],paste0,"\n"))

## ** Extract estimated coefficients

## chunk 64
coef(eUN.lmm)

## chunk 65
coef(eUN.lmm, effects = "variance")

## chunk 66
coef(eUN.lmm, effects = "variance", transform.k = "sd")

## ** Extract estimated coefficient and associated uncertainty

## chunk 67
model.tables(eUN.lmm)

## chunk 68
model.tables(eUN.lmm, effect = c("variance","correlation"))

## chunk 69
model.tables(eUN.lmm, columns = c("estimate","p.value"))

## chunk 70
model.tables(eUN.lmm, columns = add("statistic"))

## ** Extract estimated residual variance-covariance structure

## chunk 71
Sigma <- sigma(eUN.lmm)
Sigma

## chunk 72
round(Sigma,3)

## chunk 73
cov2cor(Sigma)

## chunk 74
round(cov2cor(Sigma), 3)

## chunk 75
sigma(eUN.lmm, cluster = 5)

## chunk 76
newdata <- data.frame(id = "X", time = c("-13","-1","1","13"))
sigma(eUN.lmm, cluster = newdata)

## ** Marginal effects

## chunk 77
effects(eUN.lmm, variable = "group")

## chunk 78
effects(eUN.lmm, type = "change", variable = "group")

## chunk 79
effects(eUN.lmm, type = "auc", variable = "group")

## chunk 80
effects(eUN.lmm, type = "difference", variable = "group")

## chunk 81
effects(eUN.lmm, type = c("change","difference"), variable = "group")

## chunk 82
effects(eUN.lmm, type = c("auc","difference"), variable = "group")

## ** Random effects

## chunk 83
eRI.lmm <- lmm(glucagonAUC ~ visit*group + (1|id), data = gastricbypassL)
eRI.lmm

## chunk 84
eNRI.lmm <- lmm(glucagonAUC ~ visit*group + (1|id/baseline), data = gastricbypassL)
eNRI.lmm

## chunk 85
head(ranef(eRI.lmm, format = "wide"))

## chunk 86
head(ranef(eNRI.lmm, format = "wide"))

## chunk 88
ranef(eRI.lmm, effects = "variance",
      format = "wide")

## chunk 89
ranef(eRI.lmm, effects = "variance", format = "wide")
cat(" \n")
cat(" \n")

## chunk 90
ranef(eNRI.lmm, effects = "variance",
      format = "wide")

## chunk 91
head(ranef(eRI.lmm, se = TRUE))

## ** Sum of squares

## chunk 92
sigma2 <- coef(eCS.lmm, effect = "variance")^2
tau <- coef(eCS.lmm, effect = "correlation")*sigma2
delta <- unname(sigma2 - tau)

## chunk 93
df.res <- df.residual(eCS.lmm)
SSE <- df.res * delta
c(df.res = df.res, SSE = SSE)

## chunk 94
eBeta.lmm <- coef(eCS.lmm)
eVcov.lmm <- vcov(eCS.lmm, type.information = "expected")

## chunk 95
attr(model.matrix(eCS.lmm),"assign")

## chunk 96
SSRstar.time <- eBeta.lmm[2:4] %*% solve(eVcov.lmm[2:4,2:4]) %*% eBeta.lmm[2:4] 
SSRstar.group <- eBeta.lmm[5] %*% solve(eVcov.lmm[5,5]) %*% eBeta.lmm[5] 

## chunk 97
SSR.time <- as.double(SSRstar.time * delta)
SSR.group <- as.double(SSRstar.group * delta)
c(time = SSR.time, group = SSR.group)

## ** Proportion of explained variance and partial correlation

## chunk 99
c(SSR.time/ (SSR.time + SSE),
  SSR.group/ (SSR.group + SSE))

## chunk 100
eCS.R2 <- partialCor(eCS.lmm, R2 = TRUE)
summary(eCS.R2)

## chunk 101
aCS.aov <- anova(eCS.lmm)$multivariate
setNames(with(aCS.aov, statistic*df.num/(statistic*df.num+df.denom)), aCS.aov$test)

## ** Model diagnostic

## chunk 103
eUN.diagW <- residuals(eUN.lmm, type = "normalized", format = "wide")
colnames(eUN.diagW) <- gsub("normalized.","",colnames(eUN.diagW))
head(eUN.diagW)

## chunk 104
eUN.diagL <- residuals(eUN.lmm, type = "normalized", format = "long", keep.data = TRUE)
head(eUN.diagL)

## chunk 105
plot(eUN.lmm, type = "scatterplot")

## chunk 106
plot(eUN.lmm, type = "scatterplot2")

## chunk 107
plot(eUN.lmm, type = "correlation", type.residual = "response")
plot(eUN.lmm, type = "correlation", type.residual = "normalized")

## chunk 109
plot(eUN.lmm, type = "qqplot", engine = "qqtest",
     facet = ~time, labeller = "label_both", facet_nrow=1)
## Note: the qqtest package to be installed to use the argument engine.plot = "qqtest" 

## chunk 110
eUN.lmm_profile <- profile(eUN.lmm, effects = c("sigma","rho(-13,-1)"))
plot(eUN.lmm_profile)

## ** Visualize model fit

## chunk 111
## left panel
plot(eUN.lmm, type = "fit", color = "group", size.text = 20)

## chunk 112
## middle panel
plot(eUN.lmm, type = "fit", color = "group", ci.alpha = NA, size.text = 20)

## chunk 113
## right panel
plot(eUN.lmm, type = "fit", obs.alpha = 0.25, ci = FALSE, size.text = 20)

## chunk 114
## add baseline weight
gastricbypassLB <- merge(gastricbypassL, gastricbypassW[c("id","weight1")], by = "id")

eUN.lmmB <- lmm(glucagonAUC ~ weight1 + visit*group, repetition = ~time|id,
                structure = "UN", data = gastricbypassLB)

## chunk 115
## left panel
plot(eUN.lmmB, type = "fit", color = "group", ci = FALSE, size.text = 20)

## chunk 116
## middel panel
plot(eUN.lmmB, type = "fit", color = "group", ci = FALSE, size.text = 20,
     at = data.frame(weight1 = 150), obs.alpha = 0.2)

## chunk 117
## right panel
gg.traj <- autoplot(eUN.lmmB, type = "fit", color = "group", size.text = 20, facet =~id)
gg.traj$plot + theme(legend.position = "bottom")

## ** Partial residuals

## chunk 118
df.pres <- residuals(eUN.lmmB, type = "partial", variable = "weight1", keep.data = TRUE)
head(df.pres)

## chunk 119
## left panel
plot(eUN.lmmB, type = "partial", variable = "weight1")
## right panel
plot(eUN.lmmB, type = "partial", variable = c("(Intercept)","weight1"))

## ** Statistical inference (single model, linear)

## chunk 121
anova(eUN.lmm)

## chunk 122
anova(eUN.lmm, effects = c("visit3-visit2=0"))

## chunk 123
e.anova <- anova(eUN.lmm, effects = c("visit3-visit2=0","visit4-visit2=0"))
summary(e.anova)

## chunk 124
library(multcomp)
summary(anova(eUN.lmm, effects = mcp(visit = "Tukey")))

## chunk 125
try(
  anova(eUN.lmm,
        effects = c("log(k).-1=0","log(k).1=0","log(k).13=0"))
)

## chunk 126
name.coef <- rownames(confint(eUN.lmm, effects = "all"))
name.varcoef <- grep("^k",name.coef, value = TRUE)
C <- matrix(0, nrow = 3, ncol = length(name.coef), dimnames = list(name.varcoef, name.coef))
diag(C[name.varcoef,name.varcoef]) <- 1
C[,1:9]

## chunk 127
anova(eUN.lmm, effects = C)

## ** Statistical inference (multiple models, linear)

## chunk 128
Manova <- rbind(anova(eInd.lmm, effects = "visit3:group1 = 0", robust = FALSE),
                anova(eCS.lmm, effects = "visit3:group1 = 0", robust = FALSE),
                anova(eUN.lmm, effects = "visit3:group1 = 0", robust = FALSE),
                name = c("Ind","CS","UN"))
summary(Manova) 

## ** Statistical inference (single model, non-linear)

## chunk 129
e.ANCOVA <- lm(weight4 ~ weight1 + group, data = gastricbypassW)
summary(e.ANCOVA)$coef

## chunk 130
gastricbypassL14 <- gastricbypassL[gastricbypassL$visit %in% c(1,4),]
gastricbypassL14$visit <- droplevels(gastricbypassL14$visit)
e.lmmANCOVA <- lmm(weight ~ visit + visit:group, repetition = ~visit|id,
                   data = gastricbypassL14)

## chunk 131
lava::estimate(e.lmmANCOVA, f = function(p){
  c(Y1 = as.double(p["rho(1,4)"]*p["k.4"]),
    X1 = as.double(p["visit4:group1"]-p["rho(1,4)"]*p["k.4"]*p["visit1:group1"]))
})

## ** Baseline adjustment

## chunk 132
gastricbypassL$treat <- baselineAdjustment(gastricbypassL, variable = "group",
                                repetition = ~visit|id, constrain = c("1","2"),
                                new.level = "none")
table(treat = gastricbypassL$treat,
      visit = gastricbypassL$visit,
      group = gastricbypassL$group)

## chunk 133
table(treat = gastricbypassL$treat, visit = gastricbypassL$visit, group = gastricbypassL$group)[,,1,drop=FALSE]

## chunk 134
table(treat = gastricbypassL$treat, visit = gastricbypassL$visit, group = gastricbypassL$group)[,,2,drop=FALSE]

## chunk 135
gastricbypassL$treat2 <- baselineAdjustment(gastricbypassL, variable = "group",
                                 repetition = ~visit|id, constrain = c("1","2"))
table(treat = gastricbypassL$treat2,
      visit = gastricbypassL$visit,
      group = gastricbypassL$group)

## chunk 136
table(treat = gastricbypassL$treat2, visit = gastricbypassL$visit, group = gastricbypassL$group)[,,1,drop=FALSE]

## chunk 137
table(treat = gastricbypassL$treat2, visit = gastricbypassL$visit, group = gastricbypassL$group)[,,2,drop=FALSE]

## chunk 138
gastricbypassL$visitXtreat <- baselineAdjustment(gastricbypassL, variable = "group",
                                      repetition = ~visit|id, constrain = c("1","2"),
                                      collapse.time = ".")

table(treat = gastricbypassL$visitXtreat,
      visit = gastricbypassL$visit,
      group = gastricbypassL$group)

## chunk 139
table(treat = gastricbypassL$visitXtreat, visit = gastricbypassL$visit, group = gastricbypassL$group)[,,1,drop=FALSE]

## chunk 140
table(treat = gastricbypassL$visitXtreat, visit = gastricbypassL$visit, group = gastricbypassL$group)[,,2,drop=FALSE]

## chunk 141
eC.lmm <- lmm(glucagonAUC ~ visitXtreat, data = gastricbypassL,
              repetition = ~visit|id, structure = "UN")
coef(eC.lmm) ## change from baseline

## chunk 142
eC2.lmm <- lmm(glucagonAUC ~ 0 + visitXtreat, data = gastricbypassL,
              repetition = ~visit|id, structure = "UN")
coef(eC2.lmm) ## absolute value

## chunk 143
colnames(model.matrix(glucagonAUC ~ treat*visit, data = gastricbypassL))

## chunk 144
eC3.lmm <- lmm(glucagonAUC ~ treat2*visit, data = gastricbypassL,
               repetition = ~visit|id, structure = "UN")

## chunk 145
model.tables(eC3.lmm)

## chunk 146
plot(eC3.lmm, color = "group", ci = FALSE, size.text = 20, obs.alpha = 0.1)

## chunk 147
effects(eC3.lmm, variable = "treat2", type = "difference")

## ** Predictions

## chunk 148
news <- gastricbypassL[gastricbypassL$id==2,]
news$glucagon <- 0
predict(eUN.lmm, newdata = news, se = TRUE)

## chunk 149
X.12 <- model.matrix(formula(eUN.lmm), news)
X.12

## chunk 150
X.12 %*% coef(eUN.lmm)

## chunk 151
newd <- rbind(
  data.frame(id = 1, time = -13, visit = "1", group = 0, glucagonAUC = coef(eUN.lmm)["(Intercept)"]),
  data.frame(id = 1, time = 1, visit = "3", group = 0, glucagonAUC = NA),
  data.frame(id = 2, time = -13, visit = "1", group = 0, glucagonAUC = 50),
  data.frame(id = 2, time = 1, visit = "3", group = 0, glucagonAUC = NA)
)
predict(eUN.lmm, newdata = newd, type = "dynamic", keep.data = TRUE)

## chunk 152
mu1 <- coef(eUN.lmm)["(Intercept)"]
mu3 <- mu1 + coef(eUN.lmm)["visit3"]
Omega_11 <- sigma(eUN.lmm)[1,1]
Omega_31 <- sigma(eUN.lmm)[3,1]
as.double(mu3 + Omega_31 * (50 - mu1) / Omega_11)

## * Equivalence with other statistical methods
## ** Welch two sample t-test

## chunk 153
t.test(weight4 ~ group, data = gastricbypassW)

## chunk 154
e.ttest4 <- lmm(weight4 ~ group, structure = IND(~group), 
               data = gastricbypassW, trace = FALSE)
model.tables(e.ttest4)

## ** Paired t-test

## chunk 155
t.test(gastricbypassW$weight4, gastricbypassW$weight1, paired = TRUE)

## chunk 156
e.lmm2tt <- lmm(weight ~ visit, repetition = ~visit|id, structure = "UN",
                data = gastricbypassL)
model.tables(e.lmm2tt)["visit4",,drop=FALSE]

## ** Welch two sample t-test on the change

## chunk 157
gastricbypassW.0 <- gastricbypassW[gastricbypassW$group==0,]
gastricbypassW.1 <- gastricbypassW[gastricbypassW$group==1,]
t.test(gastricbypassW.0$weight4-gastricbypassW.0$weight1,
       gastricbypassW.1$weight4-gastricbypassW.1$weight1)

## chunk 158
e.lmm2tt2 <- lmm(weight ~ visit*group, repetition = ~visit|id, structure = UN(~group),
                 data = gastricbypassL)
model.tables(e.lmm2tt2)["visit4:group1",,drop=FALSE]

## ** Multiple Student's t-test

## chunk 159
e.ttest1 <- lmm(weight1 ~ group, structure = IND(~group), 
                data = gastricbypassW, trace = FALSE)
e.ttest2 <- lmm(weight2 ~ group, structure = IND(~group), 
                data = gastricbypassW, trace = FALSE)
e.ttest3 <- lmm(weight3 ~ group, structure = IND(~group), 
                data = gastricbypassW, trace = FALSE)

## chunk 160
e.mttest <- rbind(anova(e.ttest1, effects = "group=0"),
                  anova(e.ttest2, effects = "group=0"),
                  anova(e.ttest3, effects = "group=0"),
                  anova(e.ttest4, effects = "group=0"))
model.tables(e.mttest, method = "bonferroni")

## chunk 161
e.mttest2 <- mlmm(weight ~ group, structure = IND(~group),
                  data = gastricbypassL, trace = FALSE,
                  effects = "group1=0", by = "time", repetition = ~time|id)
model.tables(e.mttest2, method = "single-step2")

## chunk 162
mt.test(weight1+weight2+weight3+weight4~group, data = gastricbypassW)

## ** Linear regression on the change 

## chunk 163
gastricbypassW$changeG41 <- gastricbypassW$glucagonAUC4-gastricbypassW$glucagonAUC1
e.change41 <- lm(changeG41 ~ weight1, data = gastricbypassW)
summary(e.change41)$coef

## chunk 164
gastricbypassL41 <- gastricbypassL[gastricbypassL$visit %in% c(1,4),]
gastricbypassL41$visit <- droplevels(gastricbypassL41$visit)
gastricbypassL41$weight1 <- gastricbypassW$weight1[gastricbypassL41$id]

e.lmm41 <- lmm(glucagonAUC ~ visit + visit*weight1,
               repetition =~ visit|id, structure = "UN",
               data = gastricbypassL41)
model.tables(e.lmm41)

## chunk 165
index.missing41 <- which(is.na(gastricbypassW$changeG41))
index.missing41

## ** Correlation between changes 

## chunk 166
gastricbypassW$changeG41 <- gastricbypassW$glucagonAUC4-gastricbypassW$glucagonAUC1
gastricbypassW$changeW41 <- gastricbypassW$weight4-gastricbypassW$weight1

## chunk 167
cor.test(gastricbypassW$changeW41, gastricbypassW$changeG41)

## chunk 168
e2.change41 <- lm(changeG41 ~ changeW41, data = gastricbypassW)
summary(e2.change41)$coef

## chunk 169
keep.col <- c("id","weight1","weight4","glucagonAUC1","glucagonAUC4")
gastricbypassL4 <- reshape(gastricbypassW[,keep.col], direction = "long",
                           idvar = "id", varying = 2:5, timevar = "type", v.names = "value")
gastricbypassL4$type <- factor(gastricbypassL4$type, labels = keep.col[-1])
gastricbypassL4 <- gastricbypassL4[order(gastricbypassL4$id),]
head(gastricbypassL4)

## chunk 170
e.lmm4 <- lmm(value ~ type,
              repetition = ~type|id, structure = "UN",
              data = gastricbypassL4)

## chunk 171
sigma.lmm4 <- sigma(e.lmm4)
sigma.lmm4

## chunk 172
Mcon <- cbind(c(-1,1,0,0),c(0,0,-1,1))
sigmeChange.lmm4 <- t(Mcon) %*% sigma.lmm4 %*% Mcon
dimnames(sigmeChange.lmm4) <- list(c("d.weight","d.glucagonAUC"),
                                   c("d.weight","d.glucagonAUC"))
sigmeChange.lmm4

## chunk 173
cov2cor(sigmeChange.lmm4)[1,2]
sigmeChange.lmm4[1,2]/sigmeChange.lmm4[1,1]

## chunk 174
estimate(e.lmm4, function(p){
  Sigma.change <- t(Mcon) %*% sigma(e.lmm4, p = p) %*% Mcon
  c(cor = cov2cor(Sigma.change)[1,2],
    beta = Sigma.change[1,2]/Sigma.change[1,1])
})

## * Missing values and imputation

## chunk 175
sss <- summarize(glucagonAUC ~ time, data = gastricbypassL, na.rm = TRUE)
cbind(sss[,1:4], pc = paste0(100 * sss$missing / (sss$missing + sss$observed), "%"))

## chunk 176
summarizeNA(data = gastricbypassL, repetition = ~ time|id)

## chunk 177
## long format
gastricbypassL32 <- gastricbypassL[gastricbypassL$visit %in% c(3,2),]
gastricbypassL32$visit <- droplevels(gastricbypassL32$visit)
gastricbypassL32$weight1 <- gastricbypassW$weight1[gastricbypassL32$id]
## wide format
gastricbypassW$changeG32 <- gastricbypassW$glucagonAUC3-gastricbypassW$glucagonAUC2

## ** Full information approach

## chunk 178
e.lmm32 <- lmm(glucagonAUC ~ visit + visit*weight1,
               repetition =~ visit|id, structure = "UN",
               data = gastricbypassL32)
model.tables(e.lmm32)

## chunk 179
e.change32 <- lm(changeG32 ~ weight1, data = gastricbypassW)
summary(e.change32)$coef

## chunk 180
coef(lm(changeG32 ~ weight1, data = gastricbypassW[-c(5,15),]))

## chunk 181
gastricbypassWA <- fitted(e.lmm32, type = "outcome", format = "wide")
gastricbypassWA$change32 <- gastricbypassWA$glucagonAUC_3 - gastricbypassWA$glucagonAUC_2
gastricbypassWA$weight1 <- gastricbypassW$weight1[match(gastricbypassW$id,gastricbypassWA$id)]
coef(lm(change32 ~ weight1, data = gastricbypassWA))

## ** Complete case approach

## chunk 182
e.lmmCC <- lmmCC(e.change32, repetition = changeG32 ~ glucagonAUC3-glucagonAUC2|id)
model.tables(e.lmmCC)

## chunk 183
summary(e.change32)$coef

## chunk 184
gastricbypassW$changeW32 <- gastricbypassW$weight3 - gastricbypassW$weight2

e2g.change32 <- lm(changeG32 ~ changeW32 + group, data = gastricbypassW)
summary(e2g.change32)$coef

## chunk 185
e2.lmmCC <-  lmmCC(e2g.change32, repetition = list(changeG32 ~ glucagonAUC3-glucagonAUC2|id,
                                                   changeW32 ~ weight3-weight2|id))
model.tables(e2.lmmCC)

## ** Imputation 

## chunk 186
eUN.lmmNA <- lmm(glucagonAUC ~ time, repetition = ~time|id, data = gastricbypassL)
nobs(eUN.lmmNA)

## chunk 187
eData <- fitted(eUN.lmmNA, type = "outcome", keep.data = TRUE)
eData <- eData[order(eData$id,eData$time),]
eData[eData$id %in% eData[eData$impute,"id"],c("id","visit","time","glucagonAUC","impute")]

## chunk 188
ggplot(eData, aes(x=time,y=glucagonAUC, group=id)) + geom_line() + geom_point(aes(color=impute))

## chunk 190
index.na <- which(is.na(gastricbypassL$glucagonAUC))
set.seed(1)
fitted(eUN.lmmNA, type = "impute", se = c(TRUE,TRUE))[index.na]
set.seed(2)
fitted(eUN.lmmNA, type = "impute", se = c(TRUE,TRUE))[index.na]
set.seed(3)
fitted(eUN.lmmNA, type = "impute", se = c(TRUE,TRUE))[index.na]

## ** Multiple imputation

## chunk 191
data(gastricbypassW, package = "LMMstar")
colSums(is.na(gastricbypassW))

## chunk 192
library(mice)
set.seed(10)
gastricbypassW.mice <- mice(gastricbypassW, m = 5, printFlag = FALSE)
gastricbypassW.NNA <- complete(gastricbypassW.mice, action = "long")
table(gastricbypassW.NNA$.imp)

## chunk 193
e.mlmm <- mlmm(glucagonAUC3~glucagonAUC2+weight2, data=gastricbypassW.NNA,
               by = ".imp", effects = "weight2=0", trace = FALSE)
model.tables(e.mlmm)

## chunk 194
model.tables(e.mlmm, method = "pool.rubin")

## chunk 195
e.mice <- with(data=gastricbypassW.mice,exp=lm(glucagonAUC3~glucagonAUC2+weight2))
summary(pool(e.mice))

## chunk 196
plot(e.mlmm, method = c("pool.rubin","none"))

## * Data generation

## chunk 198
set.seed(10) ## ensure reproductibility
n.obs <- 100
n.times <- 4
mu <- rep(0,4)
gamma <- matrix(0, nrow = n.times, ncol = 10) ## add interaction
gamma[,6] <- c(0,1,1.5,1.5)
dW <- sampleRem(n.obs, n.times = n.times, mu = mu, gamma = gamma, format = "wide")
head(round(dW,3))

## chunk 199
set.seed(10) ## ensure reproductibility
dL <- sampleRem(n.obs, n.times = n.times, mu = mu, gamma = gamma, format = "long")
head(dL)

## * Modifying default options

## chunk 200
LMMstar.options("type.information")

## chunk 201
LMMstar.options(type.information = "expected")

## chunk 202
LMMstar.options(reinitialise = TRUE)

## * R session

## chunk 203
sessionInfo()

## * References
## * Likelihood in a linear mixed model
## ** Log-likelihood
## ** Score
## ** Hessian
## ** Degrees of freedom
## * Likelihood ratio test with the REML criterion

## chunk 204
## data(dfL, package = "LMMstar")
dfTest <- gastricbypassL[!is.na(gastricbypassL$glucagonAUC),]
dfTest$gluc <- dfTest$glucagonAUC
dfTest$gluc2 <- dfTest$glucagonAUC*2

## chunk 205
eML.UN <- lmm(weight ~ time+gluc, data = dfTest, repetition = ~time|id, method = "ML")
eML.UN2 <- lmm(weight ~ time+gluc, data = dfTest, repetition = ~time|id, method = "ML")
c(logLik(eML.UN), logLik(eML.UN2), logLik(eML.UN) - logLik(eML.UN2))

## chunk 206
eREML.UN <- lmm(weight ~ time + gluc, data = dfTest, repetition = ~time|id, method = "REML")
eREML.UN2 <- lmm(weight ~ time + gluc2, data = dfTest, repetition = ~time|id, method = "REML")
c(logLik(eREML.UN), logLik(eREML.UN2), logLik(eREML.UN) - logLik(eREML.UN2), log(2))

## chunk 207
set.seed(5) 
dfTest$ff <- rbinom(NROW(dfTest), size = 1, prob = 0.5)
logLik(lmm(weight ~ time+gluc, data = dfTest, repetition = ~time|id, method = "REML"))
logLik(lmm(weight ~ time+gluc*ff, data = dfTest, repetition = ~time|id, method = "REML"))

## chunk 208
logLik(lmm(weight ~ time + gluc, data = dfTest, repetition = ~time|id, method = "ML"))
logLik(lmm(weight ~ time + gluc*ff, data = dfTest, repetition = ~time|id, method = "ML"))

## * Sum of squares in a linear mixed model

## chunk 209
df.aov <- gastricbypassL[!is.na(gastricbypassL$glucagon),]

## chunk 210
e.lm <- lm(weight ~ visit + glucagonAUC, data = df.aov)
car::Anova(e.lm, type = "II")

## chunk 212
e.lmm <- lmm(weight ~ visit + glucagonAUC, data = df.aov)

## chunk 213
SSEstar <- crossprod(residuals(e.lmm, type = "normalized"))
c(SSEstar = SSEstar, SSE = SSEstar * sigma(e.lmm))

## chunk 214
df.residual(e.lmm)

## chunk 215
eBeta.lmm <- coef(e.lmm)
eVcov.lmm <- vcov(e.lmm, type.information = "expected")

SSRstar.glucagon <- eBeta.lmm[5] %*% solve(eVcov.lmm[5,5]) %*% eBeta.lmm[5] 
SSRstar.time <- eBeta.lmm[2:4] %*% solve(eVcov.lmm[2:4,2:4]) %*% eBeta.lmm[2:4] 
c(SSR.glucagon = SSRstar.glucagon * sigma(e.lmm),
  SSR.time = SSRstar.time * sigma(e.lmm),
  F.glucagon = SSRstar.glucagon,
  F.time = SSRstar.time/3)

## chunk 216
R2.glucagon <- SSRstar.glucagon/(SSRstar.glucagon+SSEstar)
R2.glucagon

## chunk 217
sign(coef(e.lmm)["glucagonAUC"])*sqrt(R2.glucagon)

## chunk 218
summary(partialCor(e.lmm, R2 = TRUE))

## * Equivalence with other R packages
## ** nlme package

## chunk 219
library(nlme)

## chunk 220
eRI.lmm <- lmm(weight ~ visit*group, structure = "RE",
               data = gastricbypassL, repetition = ~visit|id)
eCS.gls <- gls(weight ~ visit*group, correlation = corCompSymm(form=~visit|id),
               data = gastricbypassL, na.action = na.omit)
eCS.lme <- lme(weight ~ visit*group, random = ~1|id,
               data = gastricbypassL, na.action = na.omit)
logLik(eRI.lmm)
logLik(eCS.lme)
logLik(eCS.gls)

## chunk 221
range(ranef(eRI.lmm)-ranef(eCS.lme))

## chunk 222
eUN.gls <- gls(glucagonAUC ~ visit*group,
               correlation = corSymm(form=~as.numeric(visit)|id),
               weights = varIdent(form=~1|visit),
               data = gastricbypassL, na.action = na.omit)
logLik(eUN.gls)
logLik(eUN.lmm)

## ** lme4 package

## chunk 223
library(lme4)
library(lmerTest)

## chunk 224
eRI.lmer <- lmer(weight ~ visit*group + (1|id),
                 data = gastricbypassL)
logLik(eRI.lmer)
logLik(eRI.lmm)

## chunk 225
range(ranef(eRI.lmm)-ranef(eRI.lmer)$id)

## chunk 226
eNRI.lmm <- lmm(weight ~ visit*group, structure = RE(~(1|id/baseline)),
               data = gastricbypassL, repetition = ~visit|id)
eNRI.lmer <- lmer(weight ~ visit*group + (1|id/baseline),
                  data = gastricbypassL)
logLik(eNRI.lmer)
logLik(eNRI.lmm)

## chunk 227
eRanefNRI.lmm <- ranef(eNRI.lmm, format = "wide")
eRanefNRI.lmer <- ranef(eNRI.lmer)
## id
range(eRanefNRI.lmm$estimate-eRanefNRI.lmer$id)
## baseline
range(c(eRanefNRI.lmm$estimate.FALSE,eRanefNRI.lmm$estimate.TRUE)-ranef(eNRI.lmer)$`baseline:id`)

## chunk 228
eUN.lmer <- lmer(glucagonAUC ~ visit*group + (0 + visit|id),
                 data = gastricbypassL,
                 control = lmerControl(check.nobs.vs.nRE = "ignore"))
logLik(eUN.lmer)
logLik(eUN.lmm)

## chunk 229
anova(eUN.lmm)

## chunk 230
## only the last line is comparable
anova(eUN.lmer)

## chunk 231
data("Penicillin")
eCRI.lmer <- lmer(diameter ~ 1 + (1|plate) + (1|sample), Penicillin)
logLik(eCRI.lmer)

## chunk 232
Penicillin$index <- paste(Penicillin$sample,Penicillin$plate,sep=".")
Penicillin$id <- 1

eCRI.lmm <- lmm(diameter ~ 1 + (1|plate) + (1|sample), data = Penicillin)
logLik(eCRI.lmm)

## chunk 233
range(ranef(eCRI.lmm)$estimate-rbind(ranef(eCRI.lmer)$plate,ranef(eCRI.lmer)$sample))

## ** mmrm package

## chunk 234
library(mmrm)
e.mmrm <- mmrm(
  formula = FEV1 ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID),
  data = fev_data
)

## chunk 235
e.lmm <- lmm(
  formula = FEV1 ~ RACE + SEX + ARMCD * AVISIT,
  repetition = ~ AVISIT | USUBJID, structure = "UN",
  data = fev_data, type.information = "expected"
)

## chunk 236
logLik(e.mmrm) - logLik(e.lmm)
range(coef(e.mmrm) - coef(e.lmm))
range(vcov(e.mmrm) - vcov(e.lmm))

## ** emmeans package

## chunk 240
gastricbypassLB$group2 <- gastricbypassLB$weight1>150

## chunk 241
eCS.lmm_2 <- lmm(glucagonAUC ~ visit*group2, repetition =~visit|id, structure = "CS", data = gastricbypassLB)
logLik(eCS.lmm_2)

## chunk 242
eRI.lmer_2 <- lmer(glucagonAUC ~ visit*group2 + (1|id), data = gastricbypassLB)
logLik(eRI.lmer_2)

## chunk 243
effects(eCS.lmm_2, variable = NULL)

## chunk 244
library(emmeans)
emmeans(eRI.lmer_2, specs=~visit)

## chunk 245
table(gastricbypassLB$group2)/NROW(gastricbypassLB)

## chunk 246
eCS.elmm_2 <- model.tables(effects(eCS.lmm_2, variable = "group2"))
eCS.elmm_2

## chunk 247
0.5*eCS.elmm_2[eCS.elmm_2$group2==FALSE,"estimate"]+0.5*eCS.elmm_2[eCS.elmm_2$group2==TRUE,"estimate"]

## chunk 248
0.8*eCS.elmm_2[eCS.elmm_2$group2==FALSE,"estimate"]+0.2*eCS.elmm_2[eCS.elmm_2$group2==TRUE,"estimate"]

## chunk 249
mu.group1 <-  as.double(coef(e.group)["(Intercept)"])
mu.group2 <-  as.double(coef(e.group)["(Intercept)"] + coef(e.group)["group2TRUE"])
p.group1 <- 14/20          ; p.group2 <- 6/20
c(emmeans = (mu.group1+mu.group2)/2, predict = mu.group1 * p.group1 + mu.group2 * p.group2)

## ** effectsize package (\(R^2\) or \(\eta^2\))

## chunk 250
library(effectsize)
eta_squared(eCS.lmer)
cat("\n")

## chunk 251
eCS.Wald <- anova(eCS.lmm)$multivariate
eCS.Wald$df.num*eCS.Wald$statistic/(eCS.Wald$df.num*eCS.Wald$statistic+eCS.Wald$df.denom)

## chunk 252
eUN.Wald <- anova(eUN.lmm)$multivariate
eUN.Wald$df.num*eUN.Wald$statistic/(eUN.Wald$df.num*eUN.Wald$statistic+eUN.Wald$df.denom)

## chunk 253
eta_squared(eUN.lmer)
cat("\n")

## ** MuMIn package (\(R^2\))

## chunk 254
library(MuMIn)
r.squaredGLMM(eCS.lmer)
cat("\n")

## chunk 255
sigmaW <- sigma(eCS.lmm)[1,1]-sigma(eCS.lmm)[1,2]

## chunk 256
sigmaB <- sigma(eCS.lmm)[1,2]

## chunk 257
sigma2_XB <- var(fitted(eCS.lmm))

## chunk 258
c(R2m = sigma2_XB/(sigmaW + sigmaB + sigma2_XB),
  R2c = (sigma2_XB + sigmaB)/(sigmaW + sigmaB + sigma2_XB))

## ** stats package (partial residuals)

## chunk 264
gastricbypassW$group <- as.factor(as.numeric(gastricbypassW$id)%%2)
eIID.lm <- lm(weight4 ~ group + weight1, data = gastricbypassW)
pRes.lm <- residuals(eIID.lm, type = "partial")
head(pRes.lm)

## chunk 265
eIID.lmm <- lmm(weight4 ~ group + weight1, data = gastricbypassW)
(residuals(eIID.lmm, type = "partial", variable = "group") - pRes.lm[,"group"])
(residuals(eIID.lmm, type = "partial", variable = "weight1") - pRes.lm[,"weight1"])

## chunk 266
coef(eIID.lm)["group1"] * mean(gastricbypassW$group=="1")
coef(eIID.lm)["weight1"] * mean(gastricbypassW$weight1)

## chunk 267
(residuals(eIID.lmm, type = "partial-center", variable = "weight1") - pRes.lm[,"weight1"])

