Nesta abordagem serão ajustados 3 modelos de regressão linear com efeitos mistos
Carregar os pacotes - verifique a necessidade de instalar pacotes novos - tirando o comentário (#) para instalar pela primeira vez
require(DT) #para a função datatable
require(tidyverse)
#devtools::install_github("tidymodels/broom")
#install.packages("mice")
require(mice)
#install.packages("broom")
#install.packages("broom.mixed")
require(broom.mixed)
require(lme4)
data(potthoffroy)
datatable(potthoffroy,options = list(pageLength = 5))
pivotar_long = function(dataset_in){
dataset_in %>%
`colnames<-`(c("id","sex","8","10","12","14")) %>%
pivot_longer(!id:sex, names_to = "age", values_to = "distance") %>%
mutate(age = as.numeric(age))
}
dados_long=pivotar_long(potthoffroy)
datatable(dados_long,cap="Tabela 1: potthoffroy no formato long table",options = list(pageLength = 5))
dados_long %>%
ggplot(aes(x=age,y=distance,fill=sex)) +
geom_boxplot()+
facet_wrap(~sex)
ggplot(dados_long,aes (x = age, y = distance, color = as.factor(id))) +
geom_point() +
geom_line() +
facet_wrap(~sex)+
theme(legend.position = "none")
dados_long %>%
filter(sex=="F") %>%
ggplot(aes(x=age,y=distance))+
geom_point()+
geom_smooth(method="lm")+
facet_wrap(~id)+
ggtitle("Perfis de distância para o sexo F")
## `geom_smooth()` using formula 'y ~ x'
dados_long %>%
filter(sex=="M") %>%
ggplot(aes(x=age,y=distance))+
geom_point()+
geom_smooth(method="lm")+
facet_wrap(~id)+
ggtitle("Perfis de distância para o sexo M")
## `geom_smooth()` using formula 'y ~ x'
interaction.plot(x.factor = dados_long$age,
trace.factor = dados_long$sex,
response = dados_long$distance,
fun = mean,
type="b",
col=c("black","red"), ### Colors for levels of trace var.
pch=c(19, 17), ### Symbols for levels of trace var.
fixed=TRUE, ### Order by factor order in data
leg.bty = "o",
ylab="distance",
xlab="age")
Modelo 1: Ajustando um modelo linear misto com os dados completos
modelo_1 = lmer(distance ~ age + sex + (1 | id), data = dados_long)
modelo_1
## Linear mixed model fit by REML ['lmerMod']
## Formula: distance ~ age + sex + (1 | id)
## Data: dados_long
## REML criterion at convergence: 437.5125
## Random effects:
## Groups Name Std.Dev.
## id (Intercept) 1.807
## Residual 1.432
## Number of obs: 108, groups: id, 27
## Fixed Effects:
## (Intercept) age sexM
## 15.3857 0.6602 2.3210
broom::tidy(modelo_1, conf.int = TRUE)
## # A tibble: 5 x 8
## effect group term estimate std.error statistic conf.low conf.high
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 fixed <NA> (Intercept) 15.4 0.896 17.2 13.6 17.1
## 2 fixed <NA> age 0.660 0.0616 10.7 0.539 0.781
## 3 fixed <NA> sexM 2.32 0.761 3.05 0.829 3.81
## 4 ran_pars id sd__(Interce~ 1.81 NA NA NA NA
## 5 ran_pars Residu~ sd__Observat~ 1.43 NA NA NA NA
set.seed(11112020)
dados=potthoffroy
n = nrow(dados)
nmiss=round(0.1*n)
c=2
while(c<=6){
idmis = sample(seq(1,n,1),nmiss,replace=FALSE)
dados[idmis, c] <- NA #na coluna c vai entrar o NA
c=c+1
}
datatable(dados,cap="Tabela 2: potthoffroy com missing",options = list(pageLength = 5))
md.pattern(dados)
## id sex d8 d10 d12 d14
## 15 1 1 1 1 1 1 0
## 2 1 1 1 1 1 0 1
## 2 1 1 1 1 0 1 1
## 2 1 1 1 0 1 1 1
## 1 1 1 1 0 0 1 2
## 2 1 1 0 1 1 1 1
## 1 1 0 1 1 1 1 1
## 1 1 0 1 1 1 0 2
## 1 1 0 0 1 1 1 2
## 0 3 3 3 3 3 15
p=md.pairs(dados)
p$mr/(p$mr+p$mm)
## id sex d8 d10 d12 d14
## id NaN NaN NaN NaN NaN NaN
## sex 1 0.0000000 0.6666667 1.0000000 1.0000000 0.6666667
## d8 1 0.6666667 0.0000000 1.0000000 1.0000000 1.0000000
## d10 1 1.0000000 1.0000000 0.0000000 0.6666667 1.0000000
## d12 1 1.0000000 1.0000000 0.6666667 0.0000000 1.0000000
## d14 1 0.6666667 1.0000000 1.0000000 1.0000000 0.0000000
flux(dados)[,1:3]
## pobs influx outflux
## id 1.0000000 0.00000000 1.0000000
## sex 0.8888889 0.08843537 0.6666667
## d8 0.8888889 0.09523810 0.7333333
## d10 0.8888889 0.09523810 0.7333333
## d12 0.8888889 0.09523810 0.7333333
## d14 0.8888889 0.09523810 0.7333333
Modelo 2: Ajustando um modelo linear misto com os dados faltantes
dados_long_miss = pivotar_long(dados)
modelo_2 = lmer(distance ~ age + sex + (1 | id), data = dados_long_miss)
modelo_2
## Linear mixed model fit by REML ['lmerMod']
## Formula: distance ~ age + sex + (1 | id)
## Data: dados_long_miss
## REML criterion at convergence: 362.1519
## Random effects:
## Groups Name Std.Dev.
## id (Intercept) 1.901
## Residual 1.547
## Number of obs: 86, groups: id, 24
## Fixed Effects:
## (Intercept) age sexM
## 15.3689 0.6721 2.2762
broom::tidy(modelo_2, conf.int = TRUE)
## # A tibble: 5 x 8
## effect group term estimate std.error statistic conf.low conf.high
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 fixed <NA> (Intercept) 15.4 1.05 14.6 13.3 17.4
## 2 fixed <NA> age 0.672 0.0749 8.98 0.525 0.819
## 3 fixed <NA> sexM 2.28 0.857 2.66 0.596 3.96
## 4 ran_pars id sd__(Interce~ 1.90 NA NA NA NA
## 5 ran_pars Residu~ sd__Observat~ 1.55 NA NA NA NA
Imputação pelo pacote mice
N=100
imp <- mice(dados, m = N, print = FALSE)
imp
## Class: mids
## Number of multiple imputations: 100
## Imputation methods:
## id sex d8 d10 d12 d14
## "" "logreg" "pmm" "pmm" "pmm" "pmm"
## PredictorMatrix:
## id sex d8 d10 d12 d14
## id 0 1 1 1 1 1
## sex 1 0 1 1 1 1
## d8 1 1 0 1 1 1
## d10 1 1 1 0 1 1
## d12 1 1 1 1 0 1
## d14 1 1 1 1 1 0
## base R approach using lapply
imp_comp <- mice::complete(imp, "all")
imp_comp[[1]]
## id sex d8 d10 d12 d14
## 1 1 F 21.5 20.0 21.5 23.0
## 2 2 F 21.0 21.5 24.0 25.5
## 3 3 F 20.5 24.0 24.5 26.0
## 4 4 F 23.5 23.0 25.0 26.5
## 5 5 F 21.5 23.0 22.5 23.5
## 6 6 F 20.0 21.0 21.0 22.5
## 7 7 F 21.5 22.5 23.0 25.0
## 8 8 F 23.0 23.0 23.5 24.0
## 9 9 F 20.0 21.0 22.0 21.5
## 10 10 F 16.5 19.0 19.0 19.5
## 11 11 F 24.5 20.5 28.0 28.0
## 12 12 M 26.0 25.0 25.5 31.0
## 13 13 M 21.5 22.5 23.0 26.5
## 14 14 M 23.0 22.5 24.0 27.5
## 15 15 M 25.5 27.5 26.5 27.0
## 16 16 M 20.0 23.5 22.5 25.5
## 17 17 M 24.0 25.5 27.0 28.5
## 18 18 M 22.0 22.5 24.5 26.5
## 19 19 M 24.0 21.5 24.0 25.5
## 20 20 M 23.0 20.5 31.0 29.5
## 21 21 M 27.5 28.0 31.0 31.5
## 22 22 M 23.0 23.0 23.5 25.0
## 23 23 M 21.5 23.5 24.0 28.0
## 24 24 M 17.0 24.5 26.0 29.5
## 25 25 M 22.5 25.5 25.5 26.5
## 26 26 M 23.0 24.5 26.0 30.0
## 27 27 M 21.5 21.5 23.5 25.0
Modelo 3: Aplicar o modelo misto em todos os dados imputados
imp_comp2 = imp_comp %>%
lapply(pivotar_long)
imp_comp2[[1]]
## # A tibble: 108 x 4
## id sex age distance
## <int> <fct> <dbl> <dbl>
## 1 1 F 8 21.5
## 2 1 F 10 20
## 3 1 F 12 21.5
## 4 1 F 14 23
## 5 2 F 8 21
## 6 2 F 10 21.5
## 7 2 F 12 24
## 8 2 F 14 25.5
## 9 3 F 8 20.5
## 10 3 F 10 24
## # ... with 98 more rows
imp_comp2[[2]]
## # A tibble: 108 x 4
## id sex age distance
## <int> <fct> <dbl> <dbl>
## 1 1 M 8 22
## 2 1 M 10 20
## 3 1 M 12 21.5
## 4 1 M 14 23
## 5 2 F 8 21
## 6 2 F 10 21.5
## 7 2 F 12 24
## 8 2 F 14 25.5
## 9 3 F 8 20.5
## 10 3 F 10 24
## # ... with 98 more rows
Agora com os dados em formato long table vamos aplicar o modelo linear com efeitos mistos, da mesma forma que os modelos 1 & 2
modelo_3 <- lapply(imp_comp2, lmer, formula = distance ~ age + sex + (1 | id))
E com a função pool famos consolidar os resultados obtidos nos 100 modelos ajustados - e fazer a comparação com o primeiro modelo (missing data)
summary(modelo_1)
## Linear mixed model fit by REML ['lmerMod']
## Formula: distance ~ age + sex + (1 | id)
## Data: dados_long
##
## REML criterion at convergence: 437.5
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.7489 -0.5503 -0.0252 0.4534 3.6575
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 3.267 1.807
## Residual 2.049 1.432
## Number of obs: 108, groups: id, 27
##
## Fixed effects:
## Estimate Std. Error t value
## (Intercept) 15.38569 0.89598 17.172
## age 0.66019 0.06161 10.716
## sexM 2.32102 0.76142 3.048
##
## Correlation of Fixed Effects:
## (Intr) age
## age -0.756
## sexM -0.504 0.000
summary(modelo_2)
## Linear mixed model fit by REML ['lmerMod']
## Formula: distance ~ age + sex + (1 | id)
## Data: dados_long_miss
##
## REML criterion at convergence: 362.2
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.4555 -0.5106 0.0284 0.4259 3.1719
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 3.615 1.901
## Residual 2.393 1.547
## Number of obs: 86, groups: id, 24
##
## Fixed effects:
## Estimate Std. Error t value
## (Intercept) 15.36893 1.05412 14.580
## age 0.67210 0.07486 8.978
## sexM 2.27623 0.85724 2.655
##
## Correlation of Fixed Effects:
## (Intr) age
## age -0.786
## sexM -0.478 0.010
summary(pool(modelo_3), conf.int = TRUE)
## term estimate std.error statistic df p.value 2.5 %
## 1 (Intercept) 15.0134789 0.97387427 15.416239 93.00831 0.000000e+00 13.0795599
## 2 age 0.6948333 0.06927964 10.029402 90.84199 2.220446e-16 0.5572146
## 3 sexM 2.3538138 0.78590543 2.995034 96.87147 3.483709e-03 0.7939829
## 97.5 %
## 1 16.9473979
## 2 0.8324521
## 3 3.9136446
Nos dois artigos abaixo, sugere-se um número ótimo m de imputações: sendo a eficiência do método mensurada pela fórmula: \[ \left(1 + \frac{\lambda}{m}\right)^{-1} \] Significa que em um conjunto de dados com \(56\%\) de informações faltantes, seriam necessárias \(m=5\) imputações para se obter \(90\%\) de eficiência no método.