Sys.setlocale("LC_ALL", "es_ES.UTF-8")
[1] "LC_COLLATE=es_ES.UTF-8;LC_CTYPE=es_ES.UTF-8;LC_MONETARY=es_ES.UTF-8;LC_NUMERIC=C;LC_TIME=es_ES.UTF-8"
Presentar un resumen de las PRUEBAS ROBUSTAS (enumeradas a continuación) con 1 EJEMPLO en R para cada una de ellas y completarlo con el documento que se adjunta (“Robust statistical methods in R using WRS2 package”).
Las pruebas robustas son pruebas estadísticas que se usan cuando los datos que se quieren analizar no siguen la distribución normal, tienen outliers (valores atípicos) o siguen distribuciones de cola gruesa (con gran asimetría). Esto se debe a que las pruebas robustas no hacen suposiciones como lo hacen las pruebas paramétricas.
Debido a que pueden ser usados en situaciones que se dan más comúnmente en la naturaleza, son más útiles para comprender los datos de una forma más profunda, matizada y precisa.
Para realizar estas pruebas robustas, la libreria WRS2 de R es muy útil
Alternativas que se usan en las pruebas robustas
trim
de la librería
WRS2.
winmean
de la librería
WRS2.
Para realizar pruebas robustas para 1 sola muestra, una de las pruebas más comunes es la prueba de Wilcoxon, que se utiliza para comparar la mediana de una muestra con un valor hipotético. Se usa esta prueba debido a que no necesita suposiciones como la distribución normal, y también puede ser usado cuando se encuentran valores atípicos en los datos.
Se dispone de una muestra de datos x que se sospecha que no sigue una distribución normal. El objetivo es realizar una prueba de hipótesis para determinar si la mediana de la muestra es significativamente diferente de un valor hipotético de 10.
\[\begin{cases} H_0 : Me_m = 10 \\ H_1 : Me_m \neq 10 \end{cases}\]
set.seed(123)
x <- rnorm (50, mean = 12, sd = 3)
test_wilcoxon <- wilcox.test (x, mu = 10, alternative = "two.sided")
test_wilcoxon
Wilcoxon signed rank test with continuity correction
data: x
V = 1093, p-value = 1.122e-05
alternative hypothesis: true location is not equal to 10
Valor p = 1.121878e-05 Se recaza H_O con un nivel de significancia del 5 t, sugiriendo que la mediana de la muestra NO es igual a 10.
Las pruebas robustas para 2 muestras son una muy buena forma de determinar diferencias entre grupos cuando los datos no siguen una distribución normal o hay presencia de valores atípicos. Para probar estas diferencias, existen dos situaciones diferentes, cuando las muestras son independientes o cuando estas son pareadas.
Para el caso de tratar muestras independientes, Yuen propuso una prueba estadística para medias recortadas de 2 muestras, sin necesidad de igualdad de varianzas. Este test sigue la distribución t. También puede ser realizado sin necesidad de usar medias recortadas lo que convierte la prueba en las pruebas t de Welch con varianzas diferentes.
Sabiendo que en el dataset eurosoccer de la librería WRS2 se reúnen los datos de las 5 principales ligas europeas de fútbol, determinar si existen diferencias significativas entre los goles anotados entre las ligas de Los Países Bajos y Alemania.
Viendo que la cantidad de goles anotados de una liga no tiene ninguna relación y por lo tanto no afecta en los goles anotados de otra liga, se asume que las 2 muestras son independientes.
library (WRS2)
data (eurosoccer)
data = eurosoccer
españa = data [data$League == "Spain", ]
alemania = data [data$League == "Germany", ]
esp_ger = rbind (españa, alemania)
esp_ger$League = droplevels (esp_ger$League) #Elimina los niveles no utilizados en la columna League del nuevo conjunto de datos esp_ger
tabla = data %>% datatable (extensions = "Buttons", filter = "top",
options = list (
scrollY = "200px",
pageLength = 20, # Mostrar solo 10 filas por página
lengthMenu = c(10, 20, 40), # Opciones de selección de cantidad de filas por página
ordering = TRUE, # Permitir ordenamiento de columnas
dom = '1Bfrtip', # Definir la disposición de los elementos de la tabla
buttons = c('copy', 'csv', 'excel', 'pdf', 'print') # Agregar botones de exportación
),
class = 'compact cell-border stripe white-space nowrap' # Estilo de borde de celda y filas alternas resaltadas
)
tabla
resultado <- pb2gen (GoalsScored ~ League, data = esp_ger, est = "median")
resultado
Call:
pb2gen(formula = GoalsScored ~ League, data = esp_ger, est = "median")
Test statistic: 1, p-value = 0.80968
95% confidence interval:
-12 13
p valor = 0.8096828 Se acepta HO con un nivel de significancia del 5 t, sugiriendo que la mediana de los goles anotados en la liga Espanola y la Alemana es igual
# Calcular un valor de posición 'y' para cada anotación
comparaciones_significativas <- data.frame (
grupo1 = "Spain",
grupo2 = "Germany",
p_value = resultado$p.value)
comparaciones_significativas
grupo1 grupo2 p_value
1 Spain Germany 0.8096828
# Agregar una columna para las anotaciones de significancia basada en los p-valores
comparaciones_significativas$annotation <- ifelse(
comparaciones_significativas$p_value < 0.001, ' *** ',
ifelse(
comparaciones_significativas$p_value < 0.01, ' ** ',
ifelse(
comparaciones_significativas$p_value < 0.05, '*', 'ns'
)
)
)
comparaciones_significativas
grupo1 grupo2 p_value annotation
1 Spain Germany 0.8096828 ns
max_valor = max (data$GoalsScored, na.rm = TRUE)
espacio_entre_anotaciones = max_valor * 0.1 # ajusta este valor según sea necesario
max_valor
[1] 105
espacio_entre_anotaciones
[1] 10.5
# Agregar las posiciones 'y' al dataframe
comparaciones_significativas$y_position <- seq(from = max_valor + espacio_entre_anotaciones,
by = espacio_entre_anotaciones,
length.out = nrow(comparaciones_significativas))
comparaciones_significativas
grupo1 grupo2 p_value annotation y_position
1 Spain Germany 0.8096828 ns 115.5
# Creando el gráfico base de cajas
p <- ggplot (esp_ger, aes (x = League, y = GoalsScored) ) +
geom_boxplot (fill = "#5C7285", color = "#5C7285", alpha = 0.5) +
theme_bw () +
labs (x = "Liga", y = "Goles Anotados") +
ggtitle ("Eurosoccer") +
theme (
plot.title = element_text (size = 20, face = "bold", hjust = 0.05),
axis.text.x = element_text (size = 12),
axis.text.y = element_text (size = 12),
axis.title = element_text (size = 14, face = "bold"),
legend.position = "none")
# Añadiendo las anotaciones de significancia usando geom_signif
p <- p + geom_signif(
data = comparaciones_significativas,
aes(xmin = grupo1, xmax = grupo2, annotations = annotation, y_position = y_position),
manual = TRUE,
)
# Ajustar los limites del eje y para acomodar las anotaciones
p <- p + ylim(0, max(comparaciones_significativas$y_position) * 1.1)
# Imprimir el gráfico
p
Al igual que en el caso de muestras independientes, en la librería WRS2 también hay funciones útiles para poder determinar diferencias entre muestras pareadas. En este caso, la función yuend es muy interesante. Esta función realiza pruebas de las medias recortadas en el caso de 2 muestras pareadas. Para usar la función se puede cambiar el porcentaje de la media recortada mediante tr = … pero la función por defecto usa tr = 0.2.
Interesa comparar pesos antes y después de un tratamiento para la anorexia en un grupo de tratamiento familiar, para poder determinar si el tratamiento es eficaz para la ganancia de peso.
En este caso, como se quiere ver la diferencia de peso antes y después del tratamiento, se habla de muestras pareadas.
\[\begin{cases} H_0 : Me_{pre} = Me_{post} \\ H_1 : Me_{pre} \neq Me_{post} \end{cases}\]
library (MASS)
data (anorexia)
data = anorexia
tabla = data %>% datatable (extensions = "Buttons", filter = "top",
options = list (
scrollY = "200px",
pageLength = 20, # Mostrar solo 10 filas por página
lengthMenu = c(10, 20, 40), # Opciones de seleoción de cantidad de filas por página
ordering = TRUE, # Permitir ordenamiento de columnas
dom = '1Bfrtip', # Definir la disposición de los elementos de la tabla
buttons = c('copy', 'cav', 'excel', 'pdf', 'print') # Agregar botones de exportación
),
class = 'compact cell-border stripe white-space nowrap' # Estilo de borde de celda y filas alternas resaltadas
)
tabla
#FT = Tratamiento familiar
anorexia_FT = data [data$Treat == "FT", ]
library (tidyr)
library (dplyr)
datos_FT <- pivot_longer (anorexia_FT, cols = c(Prewt, Postwt) , names_to = "Tiempo", values_to = "Peso")
head (datos_FT)
# A tibble: 6 × 3
Treat Tiempo Peso
<fct> <chr> <dbl>
1 FT Prewt 83.8
2 FT Postwt 95.2
3 FT Prewt 83.3
4 FT Postwt 94.3
5 FT Prewt 86
6 FT Postwt 91.5
datos_FT$Tiempo = factor (datos_FT$Tiempo, levels = c("Prewt", "Postwt" ) )
head (datos_FT)
# A tibble: 6 × 3
Treat Tiempo Peso
<fct> <fct> <dbl>
1 FT Prewt 83.8
2 FT Postwt 95.2
3 FT Prewt 83.3
4 FT Postwt 94.3
5 FT Prewt 86
6 FT Postwt 91.5
FT_pre = datos_FT$Peso [datos_FT$Tiempo == "Prewt"]
FT_post = datos_FT$Peso [datos_FT$Tiempo == "Postwt"]
resultado <- yuend (FT_pre, FT_post)
resultado
Call:
yuend(x = FT_pre, y = FT_post)
Test statistic: -3.829 (df = 10), p-value = 0.00332
Trimmed mean difference: -8.56364
95 percent confidence interval:
-13.5469 -3.5804
Explanatory measure of effect size: 0.6
# Caloular un valor de posición 'y' para cada anotación
comparaciones_significativas <- data.frame (
grupo1 = "Prewt",
grupo2 = "Postwt",
p_value = resultado$p.value)
# Agregar una columna para las anotaciones de significancia basada en los p-valores
comparaciones_significativas$annotation <- ifelse (
comparaciones_significativas$p_value < 0.001, ' *** ',
ifelse (
comparaciones_significativas$p_value < 0.01, ' ** ',
ifelse (
comparaciones_significativas$p_value < 0.05, '*', 'ns'
)
)
)
max_valor = max (datos_FT$Peso, na.rm = TRUE)
espacio_entre_anotaciones = max_valor * 0.10 # ajusta este valor segun sea necesario
# Agregar las posiciones 'y' al dataframe
comparaciones_significativas$y_position <- seq(from = max_valor + espacio_entre_anotaciones/5,
by = espacio_entre_anotaciones,
length.out = nrow(comparaciones_significativas))
# Creando el gráfico base de cajas
p <- ggplot (datos_FT, aes (x = Tiempo, y = Peso) ) +
geom_boxplot (fill = "#5C7285", color = "#5C7285", alpha = 0.5) +
theme_bw () +
labs (x = "Momento del tratamiento", y = "Peso del paciente") +
ggtitle ("Tratamiento familiar de anorexia") +
theme (
plot.title = element_text (size = 20, face = "bold", hjust = 0.05),
axis.text.x = element_text (size = 12),
axis.text.y = element_text (size = 12),
axis.title = element_text (size = 14, face = "bold"),
legend.position = "none")
# Añadiendo las anotaciones de significancia usando geom signif
p <- p + geom_signif (
data = comparaciones_significativas,
aes (xmin = grupo1, xmax = grupo2, annotations = annotation, y_position = y_position) ,
manual = TRUE,)
# Ajustar los limites del eje y para acomodar las anotaciones
p <- p + ylim(70, max(comparaciones_significativas$y_position) * 1.05)
# Imprimir el gráfico
p
Un ANOVA robusto de 1 vía es una versión de la prueba ANOVA diseñada para manejar datos que no cumplen con los supuestos de normalidad y homogeneidad de varianza. Utiliza métodos robustos para calcular las estimaciones de los parámetros y las pruebas de hipótesis, lo que lo hace menos sensible a los valores atípicos y a las desviaciones de los supuestos.
Para realizar ANOVA robusto inter-sujetos primero hay que fijar que se quiere comparar.
mediway
, que realiza un ANOVA de 1 vía
sin necesidad de asumir igualdad de varianzas.
t1way
, que realiza un ANOVA de 1
vía usando medias recortadas y sin necesidad de asumir igualdad de
varianzas. Usa una generalización del método de Welch
. En
el caso de que existan diferencias se pueden realizar test
posthoc mediante el comando lincon
.
Para este ejemplo se volverá a usar el dataset eurosoccer solo que en vez de comparar los datos de solo 2 ligas europeas, se comparan la cantidad de goles anotados de todas las ligas europeas.
library (WRS2)
data (eurosoccer)
data = eurosoccer
tabla = data %>% datatable (extensions = "Buttons", filter = "top",
options = list (
scrollY = "200px",
pageLength = 20, # Mostrar solo 10 filas por página
lengthMenu = c(10, 20, 40), # Opciones de selección de oantidad de filas por página
ordering = TRUE, # Permitir ordenamiento de columnas
dom = 'lBfrtip', # Definir la disposición de los elementos de la tabla
buttons = c('copy', 'csv', 'excel', 'pdf', 'print') # Agregar botones de exportación
),
class = 'compact cell-border stripe white-space nowrap' # Estilo de borde de celda y filas alternas resaltadas
)
tabla
Primero se comparan las medianas con la función med1way
resultado_med <- med1way (GoalsScored ~ League, data = data)
resultado_med
Call:
med1way(formula = GoalsScored ~ League, data = data)
Test statistic F: 1.0397
Critical value: 2.2442
p-value: 0.301
p_thresh = 0.05
if (resultado$p.value > p_thresh) {
cat ("p valor =", resultado_med$p.value, "\n")
cat ("Se acepta HO con un nivel de significancia del", p_thresh*100, "%, sugiriendo quela mediana de los goles anotados de las ligas europeas es igual")
} else{
cat ("p valor =", resultado_med$p.value, "\n")
cat ("Se rechaza HO con un nivel de significancia del", p_thresh*100, "%, sugiriendo que la mediana de los goles anotados de las ligas europeas NO es igual")
}
p valor = 0.301
Se rechaza HO con un nivel de significancia del 5 %, sugiriendo que la mediana de los goles anotados de las ligas europeas NO es igual
Tambien se comparan las medias recortadas con la función t1way
resultado_mean <- t1way (GoalsScored ~ League, data = data)
resultado_mean
Call:
t1way(formula = GoalsScored ~ League, data = data)
Test statistic: F = 0.6291
Degrees of freedom 1: 4
Degrees of freedom 2: 27.07
p-value: 0.64594
Explanatory measure of effect size: 0.26
Bootstrap CI: [0.07; 0.42]
p_thresh = 0.05
if (resultado_mean$p.value > p_thresh) {
cat ("p valor =", resultado_mean$p.value, "\n")
cat ("Se acepta HO con un nivel de significancia del", p_thresh*100, "%, sugiriendo que la media recortada de los goles anotados de las ligas europeas es igual")
} else{
cat ("p valor =", resultado_mean$p.value, "\n")
cat ("Se rechaza HO con un nivel de significancia del", p_thresh*100, "%, sugiriendo que la media recortalia de los goles anotados de las ligas europeas NO es igual")
}
p valor = 0.645944
Se acepta HO con un nivel de significancia del 5 %, sugiriendo que la media recortada de los goles anotados de las ligas europeas es igual
Viendo los resultados de la función t1way se puede observar que no hay diferencias en la cantidad de goles anotados de las ligas europeas. Por lo tanto no haria falta realizar pruebas posthoc, pero para aprender como se usan se aplicarán de todas formas mediante la función lincon de la librería WRS2.
resultado_lincon <- lincon (GoalsScored ~ League, data = data)
resultado_lincon
Call:
lincon(formula = GoalsScored ~ League, data = data)
psihat ci.lower ci.upper p.value
England vs. Italy -4.25000 -19.40302 10.90302 0.88132
England vs. Spain -6.50000 -19.13964 6.13964 0.88132
England vs. Germany -5.08333 -21.58213 11.41546 0.88132
England vs. Netherlands -3.00000 -19.42828 13.42828 0.88132
Italy vs. Spain -2.25000 -15.72439 11.22439 0.88132
Italy vs. Germany -0.83333 -17.86787 16.20121 0.88132
Italy vs. Netherlands 1.25000 -15.71778 18.21778 0.88132
Spain vs. Germany 1.41667 -13.67553 16.50886 0.88132
Spain vs. Netherlands 3.50000 -11.50996 18.50996 0.88132
Germany vs. Netherlands 2.08333 -16.01449 20.18116 0.88132
box = ggplot (data = data, aes (x = League, y = GoalsScored) ) +
geom_boxplot (fill = "#5C7285", color = "#5C7285", alpha = 0.5) +
theme_bw () +
labs (x = "Liga", y = "Goles Anotados") +
ggtitle ("Eurosoccer") +
theme (
plot.title = element_text (size = 20, face = "bold", hjust = 0.05),
axis.text.x = element_text (size = 12),
axis.text.y = element_text (size = 12),
axis.title = element_text (size = 14, face = "bold"),
legend.position = "none"
)
# Convierte el gráfico a un gráfico interactivo con plotly
box_interactivo <- ggplotly (box)
# Muestra el gráfico interactivo
box_interactivo
El ANOVA robusto de medidas repetidas es una técnica estadística utilizada para analizar datos en los que se realizan mediciones repetidas en los mismos sujetos a lo largo del tiempo o bajo diferentes condiciones, proporciona inferencias válidas incluso cuando los supuestos del ANOVA tradicional no se cumplen.
En el caso de la librería WRS2, tenemos la función rmanova que sirve para analizar datos en los que se realizan mediciones repetidas en los mismos sujetos.
En el caso de que se encuentren diferencias significativas entre grupos se puede usar la función rmmcp para realizar pruebas posthoc y ver entre que grupos existen diferencias.
Usando el dataset (WineTasting) de la librería agricolae, diferentes catadores calan 3 tipos de vino (A, B y C) y le dan una nota en sabor. Sabiendo esto, se quiere calcular si las medias de las notas de los 3 vinos son iguales.
\[\begin{cases} H_0 : \text{Las medias de las notas de los 3 tipos de vino son iguales} \\ H_1 : \text{Al menos la media de nota de 1 de los tipos de vino difiere del resto} \end{cases}\]library (agricolae)
data (WineTasting)
data = WineTasting
tabla = data %>% datatable (extensions = "Buttons", filter = "top",
options = list (
scrollY = "200px",
pageLength = 20, # Mostrar solo 10 filas por pagina lengthMenu = c(10, 20, 40), # Opciones de selección de cantidad de filas por página
ordering = TRUE, # Permitir ordenamiento de columnas
dom = 'lBfrtip', # Definir la disposición de los elementos de la tabla
buttons = c('copy', 'csv', 'excel', 'pdf', 'print') # Agregar botones de exportacion
),
class = 'compact cell-border stripe white-space nowrap' # Estilo de borde de celda y filas alternas resaltadas
)
tabla
Taste = data$Taste
Wine = data$Wine
Taster = data$Taster
resultado <- rmanova (y = Taste, groups = Wine, block = Taster)
resultado
Call:
rmanova(y = Taste, groups = Wine, blocks = Taster)
Test statistic: F = 3.2614
Degrees of freedom 1: 1.61
Degrees of freedom 2: 20.92
p-value: 0.06761
p_thresh = 0.05
if (resultado$p.value > p_thresh) {
cat ("p valor =", resultado$p.value, "\n")
cat ("Se acepta HO con un nivel de significancia del", p_thresh*100, "$, sugiriendo que la media de nota de los 3 tipos de vino es igual")
} else {
cat ("p valor =", resultado$p.value, "\n")
cat ("Se rechaza HO con un nivel de significancia del", p_thresh*100, "$, sugiriendo que la media de nota de los 3 tipos de vino es igual")
}
p valor = 0.06760865
Se acepta HO con un nivel de significancia del 5 $, sugiriendo que la media de nota de los 3 tipos de vino es igual
Viendo los resultados de la función rmanova se puede observar que no hay diferencias en la media de nota de los tipos de vino. Por lo tanto no haría falta realizar pruebas posthoc, pero para aprender como se usan se aplicarán de todas formas mediante la función rmmcp.
resultado_posthoc <- rmmcp(y = Taste, groups = Wine, block = Taster)
resultado_posthoc
Call:
rmmcp(y = Taste, groups = Wine, blocks = Taster)
psihat ci.lower ci.upper p.value p.crit sig
Wine A vs. Wine B 0.02143 -0.02164 0.06449 0.19500 0.0500 FALSE
Wine A vs. Wine C 0.11429 0.02148 0.20710 0.00492 0.0169 TRUE
Wine B vs. Wine C 0.08214 0.00891 0.15538 0.00878 0.0250 TRUE
x <- resultado_posthoc$comp
valores_p <- x[, 6]
comparaciones <- c("Wine A vs Wine B", "Wine A vs Wine C", "Wine B vs Wine C")
p_thresh <- 0.05
for(j in 1:length (valores_p) ) {
if(valores_p[j] < p_thresh) {
cat ("Valor p = ", valores_p[j], "\n")
cat ("Se rechaza HO con un nivel de significancia del", p_thresh*100, "% Para la comparacion", comparaciones[j], "sugiriendo que existen diferencias entre la nota de estos vinos \n\n")
} else{
cat ("Valor p = ", valores_p[j], "\n")
cat ("Se acepta HO con un nivel de significancia del", p_thresh*100, "$ Para la comparacion", comparaciones [j], "sugiriendo que NO existen diferencias entre la nota de estos vinos \n\n")
}
}
Valor p = 0.1950045
Se acepta HO con un nivel de significancia del 5 $ Para la comparacion Wine A vs Wine B sugiriendo que NO existen diferencias entre la nota de estos vinos
Valor p = 0.004915566
Se rechaza HO con un nivel de significancia del 5 % Para la comparacion Wine A vs Wine C sugiriendo que existen diferencias entre la nota de estos vinos
Valor p = 0.008777396
Se rechaza HO con un nivel de significancia del 5 % Para la comparacion Wine B vs Wine C sugiriendo que existen diferencias entre la nota de estos vinos
# Calcular un valor de posición 'y' para cada anotación
comparaciones_significativas <- data.frame (
grupo1 = c("Wine A", "Wine B"),
grupo2 = c("Wine C", "Wine C"),
p_value = c(valores_p[2], valores_p[3] ) )
# Agregar una columna para las anotaciones de significancia basada en los p-valores
comparaciones_significativas$annotation <- ifelse(
comparaciones_significativas$p_value < 0.001, ' *** ',
ifelse (
comparaciones_significativas$p_value < 0.01, ' ** ',
ifelse(
comparaciones_significativas$p_value < 0.05, '*', 'ns'
)
)
)
max_valor = max (data$Taste, na.rm = TRUE)
espacio_entre_anotaciones = max_valor * 0.05 # ajusta este valor según sea necesario
# Agregar las posiciones 'y' al dataframe
comparaciones_significativas$y_position <- seq(from = max_valor + espacio_entre_anotaciones/2,
by = espacio_entre_anotaciones,
length.out = nrow(comparaciones_significativas))
# Creando el gráfico base de cajas
p <- ggplot (data, aes (x = Wine, y = Taste) ) +
geom_boxplot (fill = "#5C7285", color = "#5C7285", alpha = 0.5) +
theme_bw () +
labs (x = "Tipo de vino", y = "Nota de los catadores") +
ggtitle ("WineTasting") +
theme(
plot.title = element_text (size = 20, face = "bold", hjust = 0.05),
axis.text.x = element_text (size = 12),
axis.text.y = element_text (size = 12),
axis.title = element_text (size = 14, face = "bold"),
legend.position = "none")
# Añadiendo las anotaciones de significancia usando geom signif
p <- p + geom_signif(
data = comparaciones_significativas,
aes (xmin = grupo1, xmax = grupo2, annotations = annotation, y_position = y_position),
manual = TRUE,
)
# Ajustar los limites del eje y para acomodar las anotaciones
p <- p + ylim(4.5, max(comparaciones_significativas$y_position) *1.01)
# Imprimir el gráfico
p