FUENTE: Toda la información usada en este tutorial corresponde al equipo 00RTeam de la Universidad de Murcia y está disponible en http://gauss.inf.um.es/
Lee el fichero dieta.csv
en el que se recogen las siguientes variables y resuelve los apartados propuestos:
id
Identificador del sujeto observadoedad
grupo de edad al que pertenece el sujeto.tipoDiet
tipo de dieta que realiza.peso0
peso (kg) antes de comenzar la dieta.peso1
peso (kg) en la mitad de la dieta.peso2
peso (kg) al finalizar la dieta.
dfdieta <- read.table(file = "dieta.csv",
header = TRUE,
sep = ";",
dec = ".",
encoding = "UTF-8",
stringsAsFactors = FALSE) # cargamos los datos
head( dfdieta ) # comprobamos que se han leido bien
## id edad tipoDiet peso0 peso1 peso2
## 1 1 3 1 122.01756 108.64895 90.94509
## 2 2 3 1 140.86780 89.24381 88.86856
## 3 3 2 3 110.52651 115.39116 100.41721
## 4 4 2 3 120.74844 106.17004 105.34358
## 5 5 1 1 82.73085 96.49512 91.90629
## 6 6 2 1 118.06524 104.84634 94.96339
Comprobamos nuestros datos antes de empezar con los análisis. Para examinar la estructura de los datos se usa la función str( )
. Tenemos una muestra de 26 observaciones, y 6 variables.
str ( dfdieta ) # detalle de las variables
## 'data.frame': 24 obs. of 6 variables:
## $ id : int 1 2 3 4 5 6 7 8 9 10 ...
## $ edad : int 3 3 2 2 1 2 3 1 2 1 ...
## $ tipoDiet: int 1 1 3 3 1 1 1 1 2 3 ...
## $ peso0 : num 122 140.9 110.5 120.7 82.7 ...
## $ peso1 : num 108.6 89.2 115.4 106.2 96.5 ...
## $ peso2 : num 90.9 88.9 100.4 105.3 91.9 ...
tipoDiet
y edad
.Codificar adecuadamente las variables categóricas o cualitativas. Las variables tipoDiet
y edad
son categóricas. Ahora están como variables cuantitativas (int
números enteros “integer”), por lo que hay que codificarlas. Las transformamos a factor, de forma que R reconozca sus valores como niveles de una variable categórica. Con la función factor( )
:
dfdieta$tipoDiet <- factor ( dfdieta$tipoDiet )
dfdieta$edad <- factor ( dfdieta$edad )
str( dfdieta ) # comprobar que ahora son factor
## 'data.frame': 24 obs. of 6 variables:
## $ id : int 1 2 3 4 5 6 7 8 9 10 ...
## $ edad : Factor w/ 3 levels "1","2","3": 3 3 2 2 1 2 3 1 2 1 ...
## $ tipoDiet: Factor w/ 3 levels "1","2","3": 1 1 3 3 1 1 1 1 2 3 ...
## $ peso0 : num 122 140.9 110.5 120.7 82.7 ...
## $ peso1 : num 108.6 89.2 115.4 106.2 96.5 ...
## $ peso2 : num 90.9 88.9 100.4 105.3 91.9 ...
peso0
) según el grupo de edad al que pertenece y encuentra en qué grupos están las diferencias.
Estamos ante un ANOVA de una vía (factor entre sujetos).
ANOVA (análisis de la varianza, ANalisys Of VAriance) sirve para comparar dos o más medias. En nuestro caso, tres medias (los tres grupos de edad
).
De una vía (one-way ANOVA o ANOVA de un factor): examina la igualdad de las medias de la población para un resultado cuantitativo y una única variable categórica con dos o más niveles.
La variable dependiente (resultado) es cuantitativa: variable en la que deseamos comparar los grupos. En nuestro caso, la variable dependiente es peso0
.
Factor (o variable independiente): la variable categórica que define los grupos que deseamos comparar. En nuestro caso, edad
variable categórica de tres niveles (1, 2, 3).
Entre sujetos (between subjects): el factor varía entre los sujetos y el factor se mide solo una vez para un mismo sujeto. En nuestro caso, la variable edad
se mide una vez en cada sujeto, y la edad
varía de un sujeto a otro.
Para un ANOVA de una vía se debe comprobar el supuesto de independencia, el supuesto de normalidad y el supuesto de homocedasticidad. Despúes se estima el modelo ANOVA sobre lo que queremos probar, en nuestro caso si hay diferencias en la media de los pesos antes de comenzar la dieta según el grupo de edad al que pertenece el sujeto.
SUPUESTO DE INDEPENDENCIA de las observaciones. Se supone independencia de las observaciones cuando se aplica muestreo aleatorio. (Para el resto del ejercicio se supone independencia de las observaciones ya que todos los análisis se realizan sobre la misma muestra).
SUPUESTO DE NORMALIDAD: Realizar el contraste para normalidad. En este contraste la hipótesis nula es la hipótesis de normalidad, esto es, no hay diferencias entre nuestra distribución y una distribución normal con esa media y esa desviación típica. Para contrastar la normalidad usamos el test de Shapiro-Wilk, con la función shapiro.test( )
, que funciona bien con muestras pequeñas (menores a 50).
shapiro.test( dfdieta$peso0[dfdieta$edad == "1"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso0[dfdieta$edad == "1"]
## W = 0.853, p-value = 0.1022
shapiro.test( dfdieta$peso0[dfdieta$edad == "2"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso0[dfdieta$edad == "2"]
## W = 0.83071, p-value = 0.06038
shapiro.test( dfdieta$peso0[dfdieta$edad == "3"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso0[dfdieta$edad == "3"]
## W = 0.92652, p-value = 0.4849
Interpretación:
Para todos los grupos de edad se obtiene un p-value mayor de 0.05 (0.1022, 0.06038, 0.4849), no podemos rechazar la hipótesis nula (hipótesis de normalidad). Por lo tanto, podemos concluir que nuestros datos cumplen el supuesto de normalidad.
SUPUESTO DE HOMOCEDASTICIDAD Es la homogeneidad de varianza de la variable dependiente entre los grupos. En el contraste de homogeneidad de varianzas la hipótesis nula es la varianza es constante (no varía) en los diferentes grupos. Para contrastarla utilizamos el test de Bartlett con bartlett.test( )
, que es más robusto que otros tests cuando los datos son normales.
bartlett.test( peso0 ~ edad,
data = dfdieta )
##
## Bartlett test of homogeneity of variances
##
## data: peso0 by edad
## Bartlett's K-squared = 0.43715, df = 2, p-value = 0.8037
Interpretación:
Con un p-value = 0.8037, mayor de 0.05, no podemos rechazar la hipótesis nula. Por lo tanto suponemos homogeneidad de varianzas.
En el ANOVA de una vía la hipótesis nula \(H_{0}\) es que no hay diferencia entre las medias y la hipótesis alternativa \(H_{1}\) que al menos una de las medias difiere del resto. En nuestro caso, si el peso de cada individuo varía según el grupo de edad al que pertenece el sujeto.
Hipótesis nula es \(H_{0}: \mu_{1} = \mu_{2} = \mu_{3}\)
Hipótesis alternativa es al menos una es diferente \(H_{1}: \mu_{1} \neq \mu_{2} \neq \mu_{3}\)
El modelo ANOVA contrasta las diferencias en las medias en el peso entre los sujetos según el grupo de edad. Para estimar el modelo ANOVA de una vía se usa la función aov( )
, que sigue la estructura aov( variable dependiente ~ factor )
modelo1 <- aov( peso0 ~ edad, # var. cuantitativa con respecto al factor
data = dfdieta )
summary( modelo1 ) # para ver los rdos del anova
## Df Sum Sq Mean Sq F value Pr(>F)
## edad 2 2544 1272.0 13.46 0.000173 ***
## Residuals 21 1985 94.5
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Interpretación:
Con un p-value = 0.000173, menor de 0.05, podemos rechazar la hipótesis nula. Se acepta la hipótesis alternativa de que hay diferencia en al menos una de las medias de los grupos de edad. Es decir, la edad tiene un efecto significativo en el peso inicial.
Para conocer “Qué grupos de edad son los que difieren” se deben realizar contrastes dos a dos corrigiendo el nivel de significación. El procedimiento post-hoc contrasta las diferencias de todos los grupos e identifica aquellas diferencias que son estadísticamente significativas.
pairwise.t.test( dfdieta$peso0,
dfdieta$edad,
p.adj = "bonferroni")
##
## Pairwise comparisons using t tests with pooled SD
##
## data: dfdieta$peso0 and dfdieta$edad
##
## 1 2
## 2 0.33973 -
## 3 0.00015 0.00751
##
## P value adjustment method: bonferroni
Interpretación:
Existen diferencias significativas (p-valor < 0.05) entre el grupo de edad 3 y el grupo de edad 1 (0.00015), y entre el grupo de edad 3 y el grupo de edad 2 (0.00751). Entre los grupos de edad 1 y el 2 no existen diferencias significativas respecto a su peso inicial (0.33973, p-valor > 0.05).
peso2
) según la interacción del grupo de edad al que pertenece el sujeto y el tipo de dieta al que se somete. Representa el gráfico de interacción con la edad
en el eje x y el tipoDiet
en tres líneas diferentes.
Estamos ante un ANOVA de dos vías (varios factores entre sujetos).
De dos vías (two-way ANOVA o ANOVA de dos factores): examina la igualdad de las medias de la población para un resultado cuantitativo y dos variables categóricas o factores.
La variable dependiente (resultado) es cuantitativa: variable en la que deseamos comparar los grupos. En nuestro caso, la variable dependiente es peso2
.
Factores (o variables independientes): variables categóricas que definen los grupos que deseamos comparar. En nuestro caso, grupo de edad al que pertenece el sujeto (edad
con tres niveles) y el tipo de dieta al que se somete (tipoDiet
con tres niveles).
Entre sujetos (between subjects): donde cada factor varía entre los sujetos y cada factor se mide solo una vez para un mismo sujeto. En nuestro caso, la variable edad
se mide una vez en cada sujeto, y la edad
varía de un sujeto a otro; y cada sujeto pertenece a un solo grupo o nivel de la variable tipoDiet
.
Para un ANOVA de dos vías se debe comprobar el supuesto de independencia, el supuesto de normalidad y el supuesto de homocedasticidad. Estos supuestos se deben comprobar para el factor edad
y para el factor tipoDiet
. Esto es, se comprueba la normalidad para todos los niveles de cada factor, y se comprueba la homocedasticidad para ambos factores.
Comprobación de supuestos para el factor edad
:
SUPUESTO DE NORMALIDAD: Para contrastar la normalidad usamos el test de Shapiro-Wilk, con la función shapiro.test( )
.
shapiro.test( dfdieta$peso2[dfdieta$edad == "1"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso2[dfdieta$edad == "1"]
## W = 0.91981, p-value = 0.4284
shapiro.test( dfdieta$peso2[dfdieta$edad == "2"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso2[dfdieta$edad == "2"]
## W = 0.9739, p-value = 0.9267
shapiro.test( dfdieta$peso2[dfdieta$edad == "3"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso2[dfdieta$edad == "3"]
## W = 0.91386, p-value = 0.382
Interpretación:
Para todos los grupos de edad se obtiene un p-value mayor de 0.05 (0.4284, 0.9267, 0.382), no podemos rechazar la hipótesis nula (hipótesis de normalidad). Por lo tanto, podemos concluir que nuestros datos cumplen el supuesto de normalidad.
SUPUESTO DE HOMOCEDASTICIDAD Para contrastarla utilizamos el test de Bartlett con bartlett.test( )
, que es más robusto que otros tests cuando los datos son normales.
bartlett.test( peso2 ~ edad,
data = dfdieta )
##
## Bartlett test of homogeneity of variances
##
## data: peso2 by edad
## Bartlett's K-squared = 3.4329, df = 2, p-value = 0.1797
Interpretación:
Con un p-value = 0.1797, mayor de 0.05, no podemos rechazar la hipótesis nula. Por lo tanto suponemos homogeneidad de varianzas.
Comprobación de supuestos para el factor tipoDiet
:
SUPUESTO DE NORMALIDAD: Para contrastar la normalidad usamos el test de Shapiro-Wilk, con la función shapiro.test( )
.
shapiro.test( dfdieta$peso2[dfdieta$tipoDiet == "1"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso2[dfdieta$tipoDiet == "1"]
## W = 0.90802, p-value = 0.3403
shapiro.test( dfdieta$peso2[dfdieta$tipoDiet == "2"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso2[dfdieta$tipoDiet == "2"]
## W = 0.91767, p-value = 0.4113
shapiro.test( dfdieta$peso2[dfdieta$tipoDiet == "3"] )
##
## Shapiro-Wilk normality test
##
## data: dfdieta$peso2[dfdieta$tipoDiet == "3"]
## W = 0.96944, p-value = 0.8936
Interpretación:
Para todos los tipos de de dieta se obtiene un p-value mayor de 0.05 (0.3403, 0.4113, 0.8936), no podemos rechazar la hipótesis nula (hipótesis de normalidad). Por lo tanto, podemos concluir que nuestros datos cumplen el supuesto de normalidad.
SUPUESTO DE HOMOCEDASTICIDAD Para contrastarla utilizamos el test de Bartlett con bartlett.test( )
, que es más robusto que otros tests cuando los datos son normales.
bartlett.test( peso2 ~ tipoDiet,
data = dfdieta )
##
## Bartlett test of homogeneity of variances
##
## data: peso2 by tipoDiet
## Bartlett's K-squared = 1.5668, df = 2, p-value = 0.4568
Interpretación:
Con un p-value = 0.4568, mayor de 0.05, no podemos rechazar la hipótesis nula. Por lo tanto suponemos homogeneidad de varianzas.
El modelo ANOVA de dos vías evalúa, además de los efectos de los factores sobre la variable independiente, los efectos de la interacción entre ellas. La hipótesis nula \(H_{0}\) es que no hay interacción entre los factores.
Para estimar el modelo ANOVA de dos vías se usa la función aov( )
, con la estructura aov( variable dependiente ~ factor1 * factor2 )
Si los datos son balanceados, no importa el orden de los factores en la función aov( )
. Esto es, si ponemos factor1 * factor2
o si ponemos factor1 * factor2
.
table( dfdieta$edad )
##
## 1 2 3
## 8 8 8
table( dfdieta$tipoDiet )
##
## 1 2 3
## 8 8 8
Realizamos la estimación del modelo ANOVA de dos vías:
modelo2 <- aov( peso2 ~ edad * tipoDiet,
data = dfdieta )
summary( modelo2 )
## Df Sum Sq Mean Sq F value Pr(>F)
## edad 2 84.2 42.1 1.320 0.296
## tipoDiet 2 1391.1 695.5 21.823 3.62e-05 ***
## edad:tipoDiet 4 160.0 40.0 1.255 0.331
## Residuals 15 478.1 31.9
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Interpretación:
La variable tipoDiet tiene un efecto significativo (3.62e-05), la edad no (0.296). Respecto a la interacción, se acepta la hipótesis nula (0.331 mayor de 0.05), esto es no hay interacción entre ambas variables.
Por tanto concluimos que no hay diferencias significativas en el peso final según la interacción del grupo de edad al que pertenece el sujeto y el tipo de dieta al que se somete.
El término interacción representa el efecto conjunto de los dos factores. Con los resultados obtenidos en el modelo ANOVA (p-valor = 0.331, mayor de 0.05) hemos concluido que no hay diferencias significativas en el peso final (peso2
) según la interacción del grupo de edad al que pertenece el sujeto (edad
) y el tipo de dieta al que se somete (tipoDiet
).
La interpretación de la interacción se describe mejor visualmente. Con la función interaction.plot( )
representamos el gráfico de interacción: con la edad
en el eje x y el tipoDiet
en tres líneas diferentes. La variable dependiente peso2
en el eje y.
interaction.plot( dfdieta$edad, # factor en el eje x
dfdieta$tipoDiet, # factor representado en diferentes líneas
dfdieta$peso2, # var. dependiente
# editar el gráfico
ylim = c( 80, 130 ), # eje y
col = c( "#27ae60", "#5499c7", "#e74c3c"), # color de líneas
lty = c( 5, 1, 12 ), # tipo de líneas
lwd = 3, # grosor de línea
ylab = "Media del peso al final",
xlab = "Edad",
trace.label = "Dieta seguida" )
melt( )
del paquete reshape2
. En caso de que difieran, encuentra en qué grupos están las diferencias.
Estamos ante un ANOVA para medidas repetidas (factor intra sujetos). Se utiliza cuando se tienen varias medidas para el mismo sujeto en condiciones diferentes. No hay independencia.
Intra sujetos (within subjects): Los factores dentro de los sujetos (within) son los que se miden varias veces para el mismo sujeto. En nuestro caso, el peso se mide en varios momentos para cada sujeto: antes de comenzar la dieta peso0
, en la mitad de la dieta peso1
, al finalizar la dieta peso2
.
Como para un mismo sujeto se mide su peso en tres momentos diferentes, no hay independencia.
El análisis exige que los datos estén de una forma adecuada. Ahora tenemos en tres variables distintas (peso0
, peso1
, peso2
) el valor de cada peso medido en los diferentes periodos de tiempo. Recolocamos los datos de forma que se presenten en una nueva variable los niveles PesoPeriodo
y en otra nueva variable sus valores correspondientes PesoKg
. A partir de ahora usaremos este nuevo data frame para los análisis que hagamos.
Se utiliza la función melt( )
del paquete reshape2
:
library( reshape2 )
df.melt <- melt( dfdieta,
id = c( "id", "edad", "tipoDiet" ), # variables que no queremos tocar
measure = c( "peso0", "peso1", "peso2" ), # variables que quiero fusionar
variable.name = "PesoPeriodo", # le pongo un nombre a la nueva variable que creo
value.name = "PesoKg" ) # le pongo un nombre a esos datos
head( df.melt ) # vemos la nueva distribución de la base de datos
## id edad tipoDiet PesoPeriodo PesoKg
## 1 1 3 1 peso0 122.01756
## 2 2 3 1 peso0 140.86780
## 3 3 2 3 peso0 110.52651
## 4 4 2 3 peso0 120.74844
## 5 5 1 1 peso0 82.73085
## 6 6 2 1 peso0 118.06524
Para un ANOVA para medidas repetidas se debe comprobar el supuesto de normalidad y el supuesto de esfericidad.
SUPUESTO DE NORMALIDAD: Para contrastar la normalidad usamos el test de Shapiro-Wilk, con la función shapiro.test( )
.
shapiro.test( df.melt$PesoKg[df.melt$PesoPeriodo == "peso0"] )
##
## Shapiro-Wilk normality test
##
## data: df.melt$PesoKg[df.melt$PesoPeriodo == "peso0"]
## W = 0.98105, p-value = 0.9144
shapiro.test( df.melt$PesoKg[df.melt$PesoPeriodo == "peso1"] )
##
## Shapiro-Wilk normality test
##
## data: df.melt$PesoKg[df.melt$PesoPeriodo == "peso1"]
## W = 0.97138, p-value = 0.7012
shapiro.test( df.melt$PesoKg[df.melt$PesoPeriodo == "peso2"] )
##
## Shapiro-Wilk normality test
##
## data: df.melt$PesoKg[df.melt$PesoPeriodo == "peso2"]
## W = 0.96016, p-value = 0.4417
Interpretación:
En todos los periodos en que se mide el peso se obtiene un p-value mayor de 0.05 (0.9144, 0.7012, 0.4417), no podemos rechazar la hipótesis nula (hipótesis de normalidad). Por lo tanto, podemos concluir que nuestros datos cumplen el supuesto de normalidad.
SUPUESTO DE ESFERICIDAD (varianzas de las diferencias iguales). Para contrastarla utilizamos el Test de Mauchly. En este contraste la hipótesis nula es la hipótesis de esfericidad (\(H_{0}\): hay esfericidad).
Este test lo realiza la función ezANOVA( )
a la vez que ejecuta el modelo ANOVA. Por lo tanto, de entre la salida que da esa función, tomamos los resultados para Mauchly’s Test for Sphericity
# Test de Mauchly
# verlo directamente en el resultado que se obtiene al ejecutar la función ezANOVA( )
## $`Mauchly's Test for Sphericity`
## Effect W p p<.05
## 2 PesoPeriodo 0.9348576 0.4766505
Interpretación:
Con un p-value = 0.4766505, mayor de 0.05, no podemos rechazar la hipótesis nula. Por lo tanto suponemos que hay esfericidad.
Realizamos el modelo ANOVA para medidas repetidas con la función ezANOVA( )
, del paquete ez
:
library( ez )
options( contrasts = c( "contr.sum", "contr.poly" ) )
ezANOVA( data = df.melt,
dv = PesoKg, # variable dependiente cuantitativa
wid = id,
within = PesoPeriodo, # variable intra sujetos
type = 3 )
## Warning: Converting "id" to factor for ANOVA.
## $ANOVA
## Effect DFn DFd F p p<.05 ges
## 2 PesoPeriodo 2 46 9.007468 0.0004999883 * 0.2143998
##
## $`Mauchly's Test for Sphericity`
## Effect W p p<.05
## 2 PesoPeriodo 0.9348576 0.4766505
##
## $`Sphericity Corrections`
## Effect GGe p[GG] p[GG]<.05 HFe p[HF]
## 2 PesoPeriodo 0.9388416 0.0006806327 * 1.019405 0.0004999883
## p[HF]<.05
## 2 *
Interpretación:
Existen diferencias significativas entre el peso antes de comenzar la dieta, el peso en la mitad de la dieta, y el peso al finalizar la dieta (p-valor = 0.0004999883, menor de 0.05).
¿Qué periodos de tiempo son los que difieren? Se averigua haciendo contrastes dos a dos corrigiendo el nivel de significación. El procedimiento post-hoc contrasta las diferencias de todos los grupos e identifica aquellas diferencias que son estadísticamente significativas.
pairwise.t.test( df.melt$PesoKg,
df.melt$PesoPeriodo,
p.adj = "bonferroni")
##
## Pairwise comparisons using t tests with pooled SD
##
## data: df.melt$PesoKg and df.melt$PesoPeriodo
##
## peso0 peso1
## peso1 0.06168 -
## peso2 0.00015 0.16121
##
## P value adjustment method: bonferroni
Interpretación:
Existen diferencias significativas entre el peso antes de comenzar la dieta y el peso al finalizar la dieta (0.00015). No existen diferencias entre el peso a mitad de la dieta y el peso inicial (0.06168), ni entre el peso a mitad de la dieta y el peso al finalizar la dieta (0.16121).
La media de los pesos en cada periodo de tiempo son 115.91kg al principio de la dieta, 107.54kg a mitad de la dieta, y 100.61kg al finalizar la dieta. A través del gráfico caja observamos que el peso disminuye a medida que se avanza en la dieta, y del contraste sabemos que las diferencias de medias del peso a mitad de la dieta no son significativas. MORALEJA: Si empiezas una dieta, ¡termínala!
library( tables )
## Loading required package: Hmisc
## Loading required package: lattice
## Loading required package: survival
## Loading required package: Formula
## Loading required package: ggplot2
##
## Attaching package: 'Hmisc'
## The following objects are masked from 'package:base':
##
## format.pval, units
tabular( ( Periodo = PesoPeriodo ) ~ ( Peso = PesoKg ) * ( mean + sd ),
data = df.melt )
##
## Peso
## Periodo mean sd
## peso0 115.9 14.033
## peso1 107.5 12.662
## peso2 100.6 9.586
boxplot( df.melt$PesoKg ~ df.melt$PesoPeriodo,
varwidth = TRUE,
ylab = "Peso (kg)",
xlab = "Periodo de medición del peso",
names = c("Antes dieta", "Mitad dieta", "Dieta finalizada"),
col = c("#2980b9", "#7fb3d5", "#d4e6f1") )