Algunos gráficos para explorar los datos
A continuación se muestran ocho gráficos x-y, uno para cada número de contactos con la superficie, que muestran los guantes frente a la ausencia de guantes.
Cada individuo se representa con un punto. La media, la varianza y la covarianza se indican con un punto rojo y la elipse (distancia de Mahalanobis correspondiente al 97,5% de la población).
Se puede ver que los efectos son pequeños en comparación con la extensión de la población. La media es más alta para "sin guantes" y la media cambia un poco más arriba para más contactos superficiales (lo que puede demostrarse que es significativo). Pero el efecto es muy pequeño (en general, a $\frac{1}{4}$ reducción logarítmica), y hay muchos individuos para los que en realidad hay un mayor recuento de bacterias con los guantes.
La pequeña correlación muestra que, efectivamente, existe un efecto aleatorio de los individuos (si no hubiera un efecto de la persona, entonces no debería haber correlación entre los guantes emparejados y sin guantes). Pero es sólo un efecto pequeño y un individuo puede tener diferentes efectos aleatorios para "guantes" y "sin guantes" (por ejemplo, para todos los diferentes puntos de contacto el individuo puede tener recuentos consistentemente más altos/bajos para "guantes" que para "sin guantes").
Debajo se muestran parcelas separadas para cada uno de los 35 individuos. La idea de este gráfico es ver si el comportamiento es homogéneo y también ver qué tipo de función parece adecuada.
Nótese que el "sin guantes" está en rojo. En la mayoría de los casos la línea roja es más alta, más bacterias para los casos 'sin guantes'.
Creo que un gráfico lineal debería bastar para captar las tendencias. La desventaja del gráfico cuadrático es que los coeficientes van a ser más difíciles de interpretar (no vas a ver directamente si la pendiente es positiva o negativa porque tanto el término lineal como el cuadrático influyen en ello).
Pero lo más importante es que se ve que las tendencias difieren mucho entre los distintos individuos y, por lo tanto, puede ser útil añadir un efecto aleatorio no sólo para el intercepto, sino también para la pendiente del individuo.
Modelo
Con el modelo siguiente
- Cada individuo tendrá su propia curva ajustada (efectos aleatorios para coeficientes lineales).
- El modelo utiliza datos transformados logarítmicamente y se ajusta con un modelo lineal regular (gaussiano). En los comentarios, ameba mencionó que un enlace logarítmico no se relaciona con una distribución lognormal. Pero esto es diferente. $y \sim N(\log(\mu),\sigma^2)$ es diferente de $\log(y) \sim N(\mu,\sigma^2)$
- Se aplican ponderaciones porque los datos son heteroscedásticos. La variación es más estrecha hacia las cifras más altas. Esto se debe probablemente a que el recuento de bacterias tiene un cierto techo y la variación se debe sobre todo a la falta de transmisión de la superficie al dedo (= relacionado con recuentos más bajos). Véase también el gráfico 35. Hay principalmente unos pocos individuos para los que la variación es mucho mayor que para los demás. (vemos también colas más grandes, sobredispersión, en los gráficos qq)
- No se utiliza ningún término de intercepción y se añade un término de "contraste". Esto se hace para que los coeficientes sean más fáciles de interpretar.
.
K <- read.csv("~/Downloads/K.txt", sep="")
data <- K[K$Surface == 'P',]
Contactsnumber <- data$NumberContacts
Contactscontrast <- data$NumberContacts * (1-2*(data$Gloves == 'U'))
data <- cbind(data, Contactsnumber, Contactscontrast)
m <- lmer(log10CFU ~ 0 + Gloves + Contactsnumber + Contactscontrast +
(0 + Gloves + Contactsnumber + Contactscontrast|Participant) ,
data=data, weights = data$log10CFU)
Esto da
> summary(m)
Linear mixed model fit by REML ['lmerMod']
Formula: log10CFU ~ 0 + Gloves + Contactsnumber + Contactscontrast + (0 +
Gloves + Contactsnumber + Contactscontrast | Participant)
Data: data
Weights: data$log10CFU
REML criterion at convergence: 180.8
Scaled residuals:
Min 1Q Median 3Q Max
-3.0972 -0.5141 0.0500 0.5448 5.1193
Random effects:
Groups Name Variance Std.Dev. Corr
Participant GlovesG 0.1242953 0.35256
GlovesU 0.0542441 0.23290 0.03
Contactsnumber 0.0007191 0.02682 -0.60 -0.13
Contactscontrast 0.0009701 0.03115 -0.70 0.49 0.51
Residual 0.2496486 0.49965
Number of obs: 560, groups: Participant, 35
Fixed effects:
Estimate Std. Error t value
GlovesG 4.203829 0.067646 62.14
GlovesU 4.363972 0.050226 86.89
Contactsnumber 0.043916 0.006308 6.96
Contactscontrast -0.007464 0.006854 -1.09
código para obtener parcelas
función chemometrics::drawMahal
# editted from chemometrics::drawMahal
drawelipse <- function (x, center, covariance, quantile = c(0.975, 0.75, 0.5,
0.25), m = 1000, lwdcrit = 1, ...)
{
me <- center
covm <- covariance
cov.svd <- svd(covm, nv = 0)
r <- cov.svd[["u"]] %*% diag(sqrt(cov.svd[["d"]]))
alphamd <- sqrt(qchisq(quantile, 2))
lalpha <- length(alphamd)
for (j in 1:lalpha) {
e1md <- cos(c(0:m)/m * 2 * pi) * alphamd[j]
e2md <- sin(c(0:m)/m * 2 * pi) * alphamd[j]
emd <- cbind(e1md, e2md)
ttmd <- t(r %*% t(emd)) + rep(1, m + 1) %o% me
# if (j == 1) {
# xmax <- max(c(x[, 1], ttmd[, 1]))
# xmin <- min(c(x[, 1], ttmd[, 1]))
# ymax <- max(c(x[, 2], ttmd[, 2]))
# ymin <- min(c(x[, 2], ttmd[, 2]))
# plot(x, xlim = c(xmin, xmax), ylim = c(ymin, ymax),
# ...)
# }
}
sdx <- sd(x[, 1])
sdy <- sd(x[, 2])
for (j in 2:lalpha) {
e1md <- cos(c(0:m)/m * 2 * pi) * alphamd[j]
e2md <- sin(c(0:m)/m * 2 * pi) * alphamd[j]
emd <- cbind(e1md, e2md)
ttmd <- t(r %*% t(emd)) + rep(1, m + 1) %o% me
# lines(ttmd[, 1], ttmd[, 2], type = "l", col = 2)
lines(ttmd[, 1], ttmd[, 2], type = "l", col = 1, lty=2) #
}
j <- 1
e1md <- cos(c(0:m)/m * 2 * pi) * alphamd[j]
e2md <- sin(c(0:m)/m * 2 * pi) * alphamd[j]
emd <- cbind(e1md, e2md)
ttmd <- t(r %*% t(emd)) + rep(1, m + 1) %o% me
# lines(ttmd[, 1], ttmd[, 2], type = "l", col = 1, lwd = lwdcrit)
invisible()
}
Parcela 5 x 7
#### getting data
K <- read.csv("~/Downloads/K.txt", sep="")
### plotting 35 individuals
par(mar=c(2.6,2.6,2.1,1.1))
layout(matrix(1:35,5))
for (i in 1:35) {
# selecting data with gloves for i-th participant
sel <- c(1:624)[(K$Participant==i) & (K$Surface == 'P') & (K$Gloves == 'G')]
# plot data
plot(K$NumberContacts[sel],log(K$CFU,10)[sel], col=1,
xlab="",ylab="",ylim=c(3,6))
# model and plot fit
m <- lm(log(K$CFU[sel],10) ~ K$NumberContacts[sel])
lines(K$NumberContacts[sel],predict(m), col=1)
# selecting data without gloves for i-th participant
sel <- c(1:624)[(K$Participant==i) & (K$Surface == 'P') & (K$Gloves == 'U')]
# plot data
points(K$NumberContacts[sel],log(K$CFU,10)[sel], col=2)
# model and plot fit
m <- lm(log(K$CFU[sel],10) ~ K$NumberContacts[sel])
lines(K$NumberContacts[sel],predict(m), col=2)
title(paste0("participant ",i))
}
Parcela 2 x 4
#### plotting 8 treatments (number of contacts)
par(mar=c(5.1,4.1,4.1,2.1))
layout(matrix(1:8,2,byrow=1))
for (i in c(1:8)) {
# plot canvas
plot(c(3,6),c(3,6), xlim = c(3,6), ylim = c(3,6), type="l", lty=2, xlab='gloves', ylab='no gloves')
# select points and plot
sel1 <- c(1:624)[(K$NumberContacts==i) & (K$Surface == 'P') & (K$Gloves == 'G')]
sel2 <- c(1:624)[(K$NumberContacts==i) & (K$Surface == 'P') & (K$Gloves == 'U')]
points(K$log10CFU[sel1],K$log10CFU[sel2])
title(paste0("contact ",i))
# plot mean
points(mean(K$log10CFU[sel1]),mean(K$log10CFU[sel2]),pch=21,col=1,bg=2)
# plot elipse for mahalanobis distance
dd <- cbind(K$log10CFU[sel1],K$log10CFU[sel2])
drawelipse(dd,center=apply(dd,2,mean),
covariance=cov(dd),
quantile=0.975,col="blue",
xlim = c(3,6), ylim = c(3,6), type="l", lty=2, xlab='gloves', ylab='no gloves')
}
1 votos
Puede utilizar
NumberContacts
como factor numérico e incluir un término polinómico cuadrático/cúbico. O busque modelos mixtos aditivos generalizados.0 votos
Gracias, me preguntaba esto. algo así como: glmmPQL(UFC ~ Guantes+ poly(as.factor(NúmeroContactos),2), ~1+Guantes|Participante, family = gaussian(link = "log"), data = na.omit(K), verbose = F)
0 votos
Sí. Otra cuestión es que dudo que tengas errores gaussianos, que es lo que supone tu modelo (aunque modele las medias mediante el enlace log). Eso es algo que podrías investigar, pero podría ser que un GLM Gamma pudiera funcionar razonablemente bien. Véase por ejemplo stats.stackexchange.com/questions/77579 y los enlaces de la respuesta de Glen_b. Si es así, puedes probar
glmer
con familia gamma, ogamm4
con la familia gamma.0 votos
Gracias, señor. Definitivamente una preocupación y han estado buscando en Google las opciones de la familia / enlace por un tiempo. Acabo de probar Gamma(link="log") y parece interesante, pero no estoy seguro de que Q-Q esté de acuerdo (según el enlace que diste, gracias por eso). ¿Qué crees que falta? ¿Efectos aleatorios incorrectos?
0 votos
Si los guantes son un factor entre participantes, entonces
(1+Gloves|Participant)
no tiene sentido. Sólo puede utilizar(1 | Participant)
o(poly(NumberContacts,2) | Participant)
.0 votos
Sin embargo, si "todo el mundo realiza el experimento A seguido del experimento B ", la descripción del primer párrafo es engañosa. Ambos factores son intrasujeto.
0 votos
¿Cree que hacer una tras otra marcará la diferencia?
0 votos
¿A qué te refieres? Ya tienes los datos. Entonces, ¿participó cada participante sólo en A o en B (como da a entender el primer párrafo) o participó cada participante tanto en A como en B (como da a entender el último párrafo)?
0 votos
Veo que ya has aceptado una respuesta, pero tu modelo sigue teniendo problemas. Véase mi comentario anterior.
1 votos
@amoeba Gracias por tu ayuda. Todos los participantes hicieron B (sin guantes) seguido de A (con guantes). ¿Crees que hay otros problemas fundamentales en el análisis? Si es así estoy abierto a cualquier otra respuesta.
1 votos
Si es así, puede incluir el efecto aleatorio del guante. Además, no entiendo por qué quitas el intercepto aleatorio y por qué no incluyes todo el polinomio de 2º grado en la parte aleatoria. Y usted puede tener guante * num interacción. Así que ¿por qué no
CFU ~ Gloves * poly(NumberContacts,2) + (Gloves * poly(NumberContacts,2) | Participant)
o algo así.0 votos
@amoeba Parece interesante. No incluía un intercepto aleatorio porque, en teoría, todos deberían empezar con 0 bacterias independientemente del participante. ¿Es eso lo que preguntabas? El modelo que propones no converge, así que ¿es fiable el resultado? no da ninguna interacción importante pero tampoco es significativo poly(NumberContacts,2)2
1 votos
Ah, entiendo lo de la intercepción, pero entonces tendrías que suprimir también la intercepción fija. Además, para cero contactos debe tener cero UFC, pero con log-link esto no tiene sentido. Y usted no tiene en ninguna parte cerca de cero UFC en 1 contacto. Así que no suprimir la interceptación. No converger no es bueno, intente eliminar la interacción de la parte aleatoria:
CFU ~ Gloves * poly(NumberContacts,2) + (Gloves + poly(NumberContacts,2) | Participant)
o tal vez quitar los guantes de allíCFU ~ Gloves * poly(NumberContacts,2) + (poly(NumberContacts,2) | Participant)
...0 votos
@amoeba Entiendo lo que quieres decir sobre la intercepción. Sigue sin converger con o sin interacción. Sólo converge sin intercepto en aleatorio: 'UFC ~ Guantes+poly(NúmeroContactos,2) + (-1 + poly(NúmeroContactos,2)|Participante)'. ¿Ocurre esto habitualmente?
0 votos
No, esto es raro. También puede intentar eliminar los parámetros de correlación sustituyendo
|
con||
en todos los modelos anteriores. Como alternativa, se puede probar con otra biblioteca, por ejemploglmmTMB
.0 votos
Otra cosa son las opciones familiares y de enlaces. Los marginales de las bacterias me parecen normales en los primeros contactos, pero no tanto en los últimos (6-8 contactos). ¿Cree que esto causa problemas? También he probado algunos optimizadores después de encontrar la guía de bBolkers para resolver los problemas de convergencia.
0 votos
Puede tomar el log(CFU) y ejecutar un
lmer
para ver si puede hacerlo converger y elegir una estructura de efectos aleatorios que tenga sentido y no cause problemas de convergencia. Después puede cambiar a un GLMM Gamma y experimentar conglmer
/glmmTMB
/diferentes optimizadores/etc hasta que funcione.0 votos
Quitando la interacción converge utilizando todos los diferentes optimizadores en gmler y glmmPQL. Para el modelo que sugieres arriba CFU ~ Guantes * poly(NumeroContactos,2) + (Guantes + poly(NumeroContactos,2) | Participante) BOBYQA no se queja de la convergencia pero dice que tiene un Hessian degenerado con 4 valores propios negativos. Haciendo un lm ordinario, sugiere que existe interacción entre Guantes*NumeroContactos así que no estoy seguro de si debería dejarlo fuera en la versión gmler.
0 votos
No estoy seguro de si te refieres a la interacción en la parte fija o en la parte aleatoria. Creo que la parte fija
Gloves * poly(NumberContacts,2)
tiene sentido, así que personalmente no querría simplificarlo. Sin embargo, la parte aleatoria puede simplificarse gradualmente, partiendo de la "completa", hasta obtener un modelo que converja sin advertencias y no tenga parámetros de varianza o correlación degenerados. Es un consejo general para tratar con modelos mixtos. [cont.]0 votos
[cont.] Así que puedes intentarlo, en orden,
(Gloves * poly(NumberContacts,2) | Participant)
,(Gloves * poly(NumberContacts,2) || Participant)
,(Gloves + poly(NumberContacts,2) | Participant)
,(Gloves + poly(NumberContacts,2) || Participant)
,(poly(NumberContacts,2) | Participant)
,(poly(NumberContacts,2) || Participant)
,(1 | Participant)
-- algo así. Otro candidato es(poly(NumberContacts,2) | Participant/Gloves)
.0 votos
Gracias, es interesante. Mantener la interacción en los efectos fijos permite que Guantes * poli(NúmeroContactos,2) +(1 | Participante) funcione y Guantes * poli(NúmeroContactos,2)+(1+ poli(NúmeroContactos,2)| Participante) también converge sin queja. ¿Es una verdadera lástima que perdamos la interacción en los efectos aleatorios: (Guantes * poli(NúmeroContactos,2)| Participante) ?
1 votos
Creo que
Gloves * poly(NumberContacts,2) + (poly(NumberContacts,2) | Participant)
es un modelo bastante decente.1 votos
@amoeba ºAl final Guantes * poly(NúmeroContactos,2) + (Guantes*poly(NúmeroContactos,2) | Participante) funcionó después de eliminar un valor atípico muy bajo. Muchas gracias por toda vuestra ayuda y sugerencias.