Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Joan Riera
3 de diciembre de 2017
data("PlantGrowth")
boxplot(weight ~group, data = PlantGrowth)
Ajustemos un modelo usando aovcomo referencia.
R utiliza por defecto los llamados contrastes de tratamiento , donde cada nivel del
factor se compara con el primer nivel o el nivel de referencia (el nivel de control, en
nuestro caso). 1 Puede ver estos contrastes usando summary.lm:
summary.lm(mod0)
Call:
aov(formula = weight ~ group, data = PlantGrowth)
Residuals:
Min 1Q Median 3Q Max
-1.0710 -0.4180 -0.0060 0.2627 1.3690
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0320 0.1971 25.527 <2e-16 ***
grouptrt1 -0.3710 0.2788 -1.331 0.1944
grouptrt2 0.4940 0.2788 1.772 0.0877 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Estos contrastes son buenos si está interesado en comparar con un nivel base (por
ejemplo, un control), pero tenga en cuenta que puede que no sean adecuados para
diseños más complejos, especialmente si tiene datos desequilibrados y desea
utilizar sumas de cuadrados Tipo 3 .
Establecer tus propios contrastes
El camino rapido y sucio
Supongamos que está interesado en dos contrastes:
control versus tratamientos
tratamiento 1 versus tratamiento 2
En primer lugar, tenga en cuenta que solo puede especificar una cantidad de
contrastes igual a la cantidad de niveles de su factor menos uno (es decir, 2
contrastes en este caso).
Puede especificar sus contrastes definiendo una matriz (llamémosla BsBs), como
sigue:
# each vector becomes a column in the resulting matrix:
Bs <- cbind(c(1, -1/2, -1/2),
c(0, 1, -1))
Bs
[,1] [,2]
[1,] 1.0 0
[2,] -0.5 1
[3,] -0.5 -1
Voy a agregar nombres de columna y fila solo para que sea más legible. Los
nombres no son obligatorios, pero son útiles (especialmente los nombres de
columna):
summary.lm(mod1)
Call:
aov(formula = weight ~ group, data = PlantGrowth, contrasts = list(group
= Bs))
Residuals:
Min 1Q Median 3Q Max
-1.0710 -0.4180 -0.0060 0.2627 1.3690
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0730 0.1138 44.573 < 2e-16 ***
groupctrl vs trt -0.0410 0.1610 -0.255 0.80086
grouptrt1 vs trt2 -0.4325 0.1394 -3.103 0.00446 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
El primer parámetro nos ayuda a probar el primer contraste. La hipótesis nula para
el ttLa prueba es, como de costumbre, que el parámetro no es diferente de cero, es
decir, que la respuesta media para los tratamientos no es diferente del control (¡lo
que no implica que ambos tratamientos no sean diferentes del control!). En este
caso, aceptamos la hipótesis nula.
El segundo parámetro compara el tratamiento 1 y el tratamiento 2. El valor p está
muy por debajo del nivel de significancia de 0.05, por lo que rechazamos la
hipótesis nula.
Es muy importante que comprenda que esta forma de definir los
contrastes solo es válida si sus contrastes son independientes , es decir, no
está haciendo implícitamente la misma comparación en dos contrastes diferentes.
Puede verificar que sus contrastes sean independientes (es decir, ortogonales)
entre ellos y contra la intercepción ejecutando el siguiente código:
Si el resultado es una matriz diagonal (solo cero en la diagonal principal), está bien.
Supongamos por un momento que está interesado en los siguientes dos contrastes:
control vs tratamientos
control vs tratamiento 2
Observe cómo, implícitamente, el segundo contraste es parte del primer contraste:
no son independientes.
Usando el cheque anterior:
Que obviamente no es una matriz diagonal. En este caso, no está definiendo los
contrastes que piensa: necesitaría usar el protocolo (ligeramente) más complicado
que se explica a continuación.
B <- solve(C)
B
Ave ctrl vs trt trt1 vs trt2
[1,] 1 0.6666667 0.0
[2,] 1 -0.3333333 0.5
[3,] 1 -0.3333333 -0.5
Call:
aov(formula = weight ~ group, data = PlantGrowth, contrasts = list(group
= Bs))
Residuals:
Min 1Q Median 3Q Max
-1.0710 -0.4180 -0.0060 0.2627 1.3690
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0730 0.1138 44.573 < 2e-16 ***
groupctrl vs trt -0.0615 0.2414 -0.255 0.80086
grouptrt1 vs trt2 -0.8650 0.2788 -3.103 0.00446 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Tenga en cuenta que cuando lo haces de esta manera, los valores de los parámetros
estimados son fáciles de interpretar: se definen por su matriz de contraste C . Usaré
el paquete fractionalpara mostrar números fraccionarios:
library(fractional)
fractional(C)
[,1] [,2] [,3]
Ave 1/3 1/3 1/3
ctrl vs trt 1 -1/2 -1/2
trt1 vs trt2 . 1 -1
que es solo:
print(C)
[,1] [,2] [,3]
Ave 0.3333333 0.3333333 0.3333333
ctrl vs trt 1.0000000 -0.5000000 -0.5000000
trt1 vs trt2 0.0000000 1.0000000 -1.0000000
y el grupo significa:
mean(PlantGrowth$weight)
[1] 5.073
La segunda línea (el primer contraste) es la media de control menos la media de los
dos tratamientos:
4.661 - 5.526
[1] -0.865
Por otro lado, la matriz B nos da las medias esperadas del grupo cuando se
multiplica por el vector de coeficientes. En nuestro caso, B es:
fractional(B)
Ave ctrl vs trt trt1 vs trt2
[1,] 1 2/3 .
[2,] 1 -1/3 1/2
[3,] 1 -1/3 -1/2
b <- coef(mod1b)
b[1] - 1/3*b[2] + 1/2*b[3]
(Intercept)
4.661
control vs tratamientos
control vs tratamiento 2
# define C
C <- rbind(c(1, -1/2, -1/2), # note rbind, not cbind
c(1, 0, -1))
rownames(C) <- c("ctrl vs trt", "ctrl vs trt2")
Call:
aov(formula = weight ~ group, data = PlantGrowth, contrasts = list(group
= Bs))
Residuals:
Min 1Q Median 3Q Max
-1.0710 -0.4180 -0.0060 0.2627 1.3690
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0730 0.1138 44.573 <2e-16 ***
groupctrl vs trt -0.0615 0.2414 -0.255 0.8009
groupctrl vs trt2 -0.4940 0.2788 -1.772 0.0877 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
5.032 - 5.526
[1] -0.494
set.seed(5)
pg <- PlantGrowth[c(sample(1:10, 3), sample(11:20, 3), sample(21:30, 3)),
]
pg
weight group
3 5.18 ctrl
7 5.17 ctrl
8 4.53 ctrl
13 4.41 trt1
11 4.81 trt1
16 3.83 trt1
26 5.29 trt2
28 6.15 trt2
29 5.80 trt2
Bajo este modelo lineal, el valor esperado para una observación dada viene dado
por la siguiente expresión:
y^= X my^=Xm
donde XXes la matriz modelo , una n×pnorte×pagsmatriz ( nnorteobservaciones
veces ppagsgrupos) y μmes la p×1pags×1grupo significa vector. En R, podemos
recuperar la matriz modelo con:
(X <- model.matrix(mod0))
groupctrl grouptrt1 grouptrt2
3 1 0 0
7 1 0 0
8 1 0 0
13 0 1 0
11 0 1 0
16 0 1 0
26 0 0 1
28 0 0 1
29 0 0 1
attr(,"assign")
[1] 1 1 1
attr(,"contrasts")
attr(,"contrasts")$group
[1] "contr.treatment"
summary.lm(mod0)
Call:
aov(formula = weight ~ 0 + group, data = pg)
Residuals:
Min 1Q Median 3Q Max
-0.52 -0.43 0.06 0.22 0.46
Coefficients:
Estimate Std. Error t value Pr(>|t|)
groupctrl 4.9600 0.2513 19.73 1.10e-06 ***
grouptrt1 4.3500 0.2513 17.31 2.38e-06 ***
grouptrt2 5.7467 0.2513 22.86 4.58e-07 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.4353 on 6 degrees of freedom
Multiple R-squared: 0.9951, Adjusted R-squared: 0.9926
F-statistic: 403.9 on 3 and 6 DF, p-value: 2.612e-07
verá que las pruebas t son triviales, porque todo lo que estamos probando es si la
media de cada grupo es diferente de 0 o no:
Por lo tanto, no estamos haciendo ningún contraste entre los niveles del factor y,
por lo tanto, no estamos probando de ninguna manera si hay diferencias en las
medias entre los niveles.
Para obtener resultados más significativos, necesitamos codificar nuestras
variables de manera diferente, y ahí es donde entran los contrastes .
En R, los contrastes predeterminados se denominan contrastes de tratamiento ,
por lo que primero desarrollaremos la teoría para ellos, luego los ampliaremos a
otros contrastes estándar, ya predefinidos en R, y luego a cualquier conjunto
planificado de contrastes.
Contrastes de tratamiento
Supongamos ahora que queremos codificar nuestra variable categórica para
obtener tratamientos más significativos. Esto es equivalente a usar un conjunto
alternativo de parámetros definidos como:
b= C μb=Cm
donde CCes una p×ppags×pagsmatriz. Si CC es no singular y por lo tanto
invertible, podemos escribir:
μ = C−1b= B βm=C−1b=Bb
y podemos escribir nuestro modelo:
y^= X µ = X B by^=Xm=XBb
Se puede mostrar 3 que, si elegimos una transformación en CCtal que la primera
columna de la matriz BBes una columna de unos, esto se convierte en una
intersección (es decir, β0b0) y los parámetros restantes
( β1, ... , bp - 1b1,…,bpags−1), si se elige bien, produce contrastes significativos y, lo
que es más importante, la hipótesis nula (que todas las medias de grupo son
iguales) es verdadera si y solo si todos los βbpor encima de β0b0(es
decir, b1, ... , bp - 1b1,…,bpags−1) son iguales a cero.
Los contrastes de tratamiento se definen de tal manera que la intersección es la
media para el primer grupo de referencia, y cada uno de los coeficientes restantes
son diferencias entre cada nivel por encima del primer y el primer nivel.
Si ajustamos un modelo con los contrastes de tratamiento predeterminados:
Call:
aov(formula = weight ~ group, data = pg)
Residuals:
Min 1Q Median 3Q Max
-0.52 -0.43 0.06 0.22 0.46
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.9600 0.2513 19.734 1.1e-06 ***
grouptrt1 -0.6100 0.3554 -1.716 0.1369
grouptrt2 0.7867 0.3554 2.213 0.0688 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Recuerde desde arriba que μ=Bβm=Bb, entonces esta matriz nos dice qué
coeficientes necesitamos sumar (y multiplicado por qué valores, en este caso todos)
para obtener la media grupal. Por lo tanto, la media para el primer grupo es
solo β0b0, mientras que la media para el segundo grupo es β0+ b1b0+b1, y la media
para el tercer grupo es β0+ b2b0+b2. (¡Usted puede comprobarlo!)
En este caso, la matriz de codificación no se puede leer directamente para obtener
los contrastes (es decir, lo que probamos en cada línea de t.prueba anterior). Esto
se lee mejor en la matriz de contraste , CC, que se obtiene de la inversa de BB:
(C <- solve(B))
1 2 3
1 0 0
2 -1 1 0
3 -1 0 1
Esta es la matriz que nos ayuda a comprender cada una de las líneas de la salida
anterior (desde sumamry.lm).
Recuerda que β= C μb=Cmy, por lo tanto, la matriz de contraste multiplicada por
las medias del grupo nos da los valores de los coeficientes del modelo. Como
expresiones matemáticas:
b0= m1b0=m1
b1= m2- m1b1=m2−m1
y
b2= m3- m1b2=m3−m1
Para cada una de las pruebas t en la salida, la hipótesis nula es que el coeficiente es
cero. Por lo tanto, bajo la hipótesis nula:
m1=0m1=0
0 = m2- m1⇒μ1= m20=m2−m1⇒m1=m2
0 = m3- m1⇒μ1= m30=m3−m1⇒m1=m3
Finalmente, si recordamos que
y^= X µ = X B by^=Xm=XBb
ahora la matriz modelo es XBXB. Veamos qué obtuvimos para nuestro modelo:
model.matrix(mod.treat)
(Intercept) grouptrt1 grouptrt2
3 1 0 0
7 1 0 0
8 1 0 0
13 1 1 0
11 1 1 0
16 1 1 0
26 1 0 1
28 1 0 1
29 1 0 1
attr(,"assign")
[1] 0 1 1
attr(,"contrasts")
attr(,"contrasts")$group
[1] "contr.treatment"
que es exactamente:
X %*% B
2 3
3 1 0 0
7 1 0 0
8 1 0 0
13 1 1 0
11 1 1 0
16 1 1 0
26 1 0 1
28 1 0 1
29 1 0 1
crossprod(B)
2 3
3 1 1
2 1 1 0
3 1 0 1
que no es una matriz diagonal. (Recuerde que dos vectores son ortogonales si su
producto es cero).
Debido a que no son ortogonales, los contrastes de tratamiento no se pueden usar
con sumas de cuadrados Tipo III, lo que puede ser útil cuando el diseño no está
equilibrado. Por estas razones, otro software estadístico utiliza otros contrastes
para las variables categóricas por defecto.
Algunos de estos se pueden definir en R utilizando funciones de conveniencia
(hacer help(contr. treatment)una lista).
Helmert contrastes
Para un factor con tres niveles, la matriz de codificación B∗B∗ para contrastes de
Helmert es:
(Bs <- contr.helmert(3))
[,1] [,2]
1 -1 -1
2 1 -1
3 0 2
Es diagonal.
En los contrastes de Helmert, β0b0(la intersección) es la gran media, y los
contrastes comparan la media de cada grupo con la media de los niveles anteriores
(es decir, el grupo 2 frente al grupo 1, el grupo 3 frente a la media de los grupos 1 y
2, y así sucesivamente si hay más niveles) Esto se puede ver en la matriz de
codificación anterior (porque los contrastes son ortogonales), y más claramente en
la matriz de contraste:
(C <- solve(B))
1 2 3
[1,] 0.3333333 0.3333333 0.3333333
[2,] -0.5000000 0.5000000 0.0000000
[3,] -0.1666667 -0.1666667 0.3333333
Como fracciones:
fractional(C)
1 2 3
[1,] 1/3 1/3 1/3
[2,] -1/2 1/2 .
[3,] -1/6 -1/6 1/3
Call:
aov(formula = weight ~ group, data = pg, contrasts = list(group = contr.h
elmert))
Residuals:
Min 1Q Median 3Q Max
-0.52 -0.43 0.06 0.22 0.46
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0189 0.1451 34.587 3.89e-08 ***
group1 -0.3050 0.1777 -1.716 0.1369
group2 0.3639 0.1026 3.546 0.0121 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
model.matrix(mod.helm)
(Intercept) group1 group2
3 1 -1 -1
7 1 -1 -1
8 1 -1 -1
13 1 1 -1
11 1 1 -1
16 1 1 -1
26 1 0 2
28 1 0 2
29 1 0 2
attr(,"assign")
[1] 0 1 1
attr(,"contrasts")
attr(,"contrasts")$group
[,1] [,2]
ctrl -1 -1
trt1 1 -1
trt2 0 2
Suma contrastes
Los contrastes de suma son otra especificación de contrastes que encontrará en la
mayoría de los programas estadísticos.
Para un factor con tres niveles, la matriz de codificación, B∗B∗, es:
(Bs <- contr.sum(3))
[,1] [,2]
1 1 0
2 0 1
3 -1 -1
Call:
aov(formula = weight ~ group, data = pg, contrasts = list(group = contr.s
um))
Residuals:
Min 1Q Median 3Q Max
-0.52 -0.43 0.06 0.22 0.46
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.01889 0.14511 34.587 3.89e-08 ***
group1 -0.05889 0.20522 -0.287 0.7838
group2 -0.66889 0.20522 -3.259 0.0173 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
model.matrix(mod.sum)
(Intercept) group1 group2
3 1 1 0
7 1 1 0
8 1 1 0
13 1 0 1
11 1 0 1
16 1 0 1
26 1 -1 -1
28 1 -1 -1
29 1 -1 -1
attr(,"assign")
[1] 0 1 1
attr(,"contrasts")
attr(,"contrasts")$group
[,1] [,2]
ctrl 1 0
trt1 0 1
trt2 -1 -1
Y nos dice cómo los medios grupales están relacionados con los parámetros del
modelo:
m1= b0+ b1m1=b0+b1
m2= b0+ b2m2=b0+b2
m3= b0- b1- b2m3=b0−b1−b2
Pero realmente no podemos ver lo que se compara hasta que realmente
construimos la matriz de contraste:
C <- solve(cbind(1, Bs))
fractional(C)
1 2 3
[1,] 1/3 1/3 1/3
[2,] 2/3 -1/3 -1/3
[3,] -1/3 2/3 -1/3
Bs <- contr.sum(5)
B <- cbind(1, Bs)
fractional(solve(B))
1 2 3 4 5
[1,] 1/5 1/5 1/5 1/5 1/5
[2,] 4/5 -1/5 -1/5 -1/5 -1/5
[3,] -1/5 4/5 -1/5 -1/5 -1/5
[4,] -1/5 -1/5 4/5 -1/5 -1/5
[5,] -1/5 -1/5 -1/5 4/5 -1/5
crossprod(B)
[,1] [,2] [,3] [,4] [,5]
[1,] 5 0 0 0 0
[2,] 0 2 1 1 1
[3,] 0 1 2 1 1
[4,] 0 1 1 2 1
[5,] 0 1 1 1 2
Call:
aov(formula = weight ~ group, data = PlantGrowth, contrasts = list(group
= Bs))
Residuals:
Min 1Q Median 3Q Max
-1.0710 -0.4180 -0.0060 0.2627 1.3690
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0730 0.1138 44.573 < 2e-16 ***
groupctrl vs trt -0.0615 0.2414 -0.255 0.80086
grouptrt1 vs trt2 -0.8650 0.2788 -3.103 0.00446 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Tenga en cuenta que la parte confusa sobre cómo R trata los contrastes es que el
argumento contrasts =en aovrealidad no es pedir una matriz de contrastes, ¡sino
una matriz de codificación!
Finalmente, si va a ajustar varios modelos a un factor (o factores), puede definir los
contrastes para el factor en sí y luego usarlos aovdirectamente. Por ejemplo:
contrasts(PlantGrowth$group) <- Bs
mod <- aov(weight ~ group, data = PlantGrowth)
summary.lm(mod)
Call:
aov(formula = weight ~ group, data = PlantGrowth)
Residuals:
Min 1Q Median 3Q Max
-1.0710 -0.4180 -0.0060 0.2627 1.3690
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0730 0.1138 44.573 < 2e-16 ***
groupctrl vs trt -0.0615 0.2414 -0.255 0.80086
grouptrt1 vs trt2 -0.8650 0.2788 -3.103 0.00446 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1