Objetivo del Tutorial

Al finalizar este tutorial, el estudiante será capaz de:

  1. Comprender la lógica conceptual de ANOVA (Señal vs. Ruido).
  2. Calcular manualmente la variabilidad Inter-grupos (\(MS_B\)) e Intra-grupos (\(MS_W\)).
  3. Calcular el estadístico \(F\) y compararlo con un valor crítico.
  4. Interpretar el resultado de una prueba ANOVA.
  5. Ejecutar y analizar una prueba ANOVA completa usando la función aov() en R.

El Escenario: Ensayo de Analgésicos

Imagina que somos investigadores probando la eficacia de dos nuevos fármacos (A y B) para reducir el dolor, comparados con un Placebo (Control).

Medimos el nivel de dolor de 15 pacientes (5 por grupo) 1 hora después del tratamiento, en una escala de 0 (sin dolor) a 20 (dolor máximo).

Nuestra pregunta: ¿Existen diferencias significativas en el nivel de dolor promedio entre los tres grupos?

Datos:

Parte 1: Cálculo Manual (La Lógica “Señal vs. Ruido”)

ANOVA se basa en comparar la “Señal” (qué tan diferentes son las medias entre los grupos) con el “Ruido” (qué tanta variabilidad “natural” hay dentro de los grupos).

\[F = \frac{\text{Señal}}{\text{Ruido}} = \frac{\text{Variabilidad ENTRE grupos}}{\text{Variabilidad DENTRO de grupos}} = \frac{MS_B}{MS_W}\]

Paso 1.1: Estadísticos Básicos

Primero, calculemos las medias, varianzas y tamaños de muestra de nuestros datos.

# Definir los datos
g1_control <- c(14, 15, 16, 17, 18)
g2_farm_A <- c(12, 13, 14, 15, 16)
g3_farm_B <- c(10, 11, 12, 13, 14)

# Parámetros
k <- 3 # Número de grupos
n1 <- length(g1_control); n2 <- length(g2_farm_A); n3 <- length(g3_farm_B)
N <- n1 + n2 + n3 # Tamaño total de muestra (15)

# Medias de grupo (x_barra_i)
m1 <- mean(g1_control) # 16
m2 <- mean(g2_farm_A) # 14
m3 <- mean(g3_farm_B) # 12

# Varianzas de grupo (s_i^2)
v1 <- var(g1_control) # 0.5
v2 <- var(g2_farm_A) # 0.5
v3 <- var(g3_farm_B) # 0.5

# Media Global (x_barra_global)
todos_los_datos <- c(g1_control, g2_farm_A, g3_farm_B)
m_global <- mean(todos_los_datos) # 14

# Imprimir resultados
cat(sprintf("Media Global (Gran Media): %.2f\n", m_global))
## Media Global (Gran Media): 14.00
cat(sprintf("Grupo 1 (Control): n=%.0f, Media=%.2f, Varianza=%.2f\n", n1, m1, v1))
## Grupo 1 (Control): n=5, Media=16.00, Varianza=2.50
cat(sprintf("Grupo 2 (Fármaco A): n=%.0f, Media=%.2f, Varianza=%.2f\n", n2, m2, v2))
## Grupo 2 (Fármaco A): n=5, Media=14.00, Varianza=2.50
cat(sprintf("Grupo 3 (Fármaco B): n=%.0f, Media=%.2f, Varianza=%.2f\n", n3, m3, v3))
## Grupo 3 (Fármaco B): n=5, Media=12.00, Varianza=2.50

Nota: Elegimos datos “limpios” con varianzas iguales (0.5) para facilitar la pedagogía.

Paso 1.2: Calcular la Variabilidad ENTRE Grupos (\(MS_B\) - La Señal)

\(MS_B\) mide qué tan lejos están las medias de cada grupo (m1, m2, m3) de la media global (m_global).

MSB = (Suma de Cuadrados ENTRE) / (grados de libertad ENTRE)
\(MS_B = \frac{\sum_{i=1}^{k} n_i (\bar{x}_i - \bar{x})^2}{k-1}\)

1. Suma de Cuadrados ENTRE (\(SS_B\)):

\(SS_B = n_1(\bar{x}_1 - \bar{x})^2 + n_2(\bar{x}_2 - \bar{x})^2 + n_3(\bar{x}_3 - \bar{x})^2\)

\(SS_B = 5 \cdot (16 - 14)^2 + 5 \cdot (14 - 14)^2 + 5 \cdot (12 - 14)^2\)

\(SS_B = 5 \cdot (2)^2 + 5 \cdot (0)^2 + 5 \cdot (-2)^2\)

\(SS_B = 5 \cdot 4 + 0 + 5 \cdot 4\)

\(SS_B = 20 + 0 + 20 = 40\)

2. Grados de Libertad ENTRE (\(gl_B\)):

\(gl_B = k - 1 = 3 - 1 = 2\)

3. Cuadrado Medio ENTRE (\(MS_B\)):

\(MS_B = SS_B / gl_B = 40 / 2 = 20\)

Nuestra “Señal” (\(MS_B\)) es 20.

Paso 1.3: Calcular la Variabilidad DENTRO de Grupos (\(MS_W\) - El Ruido)

\(MS_W\) mide la variabilidad promedio dentro de los grupos. Es nuestra estimación del “ruido” aleatorio, o la varianza agrupada.

MSW = (Suma de Cuadrados DENTRO) / (grados de libertad DENTRO)
\(MS_W = \frac{\sum_{i=1}^{k} (n_i - 1) s_i^2}{N - k}\)

1. Suma de Cuadrados DENTRO (\(SS_W\)):

\(SS_W = (n_1 - 1)s_1^2 + (n_2 - 1)s_2^2 + (n_3 - 1)s_3^2\)

\(SS_W = (5 - 1) \cdot 0.5 + (5 - 1) \cdot 0.5 + (5 - 1) \cdot 0.5\)

\(SS_W = (4 \cdot 0.5) + (4 \cdot 0.5) + (4 \cdot 0.5)\)

\(SS_W = 2 + 2 + 2 = 6\)

2. Grados de Libertad DENTRO (\(gl_W\)):

\(gl_W = N - k = 15 - 3 = 12\)

3. Cuadrado Medio DENTRO (\(MS_W\)):

\(MS_W = SS_W / gl_W = 6 / 12 = 0.5\)

Nuestro “Ruido” (\(MS_W\)) es 0.5.

Interpretación rápida: El \(MS_W\) es 0.5, que es exactamente la varianza que teníamos dentro de cada grupo. ¡Tiene sentido! Es el promedio ponderado de las varianzas internas.

Paso 1.4: Calcular el Estadístico F Observado

Ahora, comparamos la Señal con el Ruido.

Fobs = MSB / MSW

\(F_{obs} = 20 / 0.5 = 40\)

Nuestro estadístico F observado es 40.


Parte 2: El Valor Crítico y la Toma de Decisión

Nuestro \(F_{obs}\) de 40 parece grande, pero… ¿es “lo suficientemente grande” como para ser estadísticamente significativo?

Paso 2.1: Hipótesis y Nivel de Significancia

  • \(H_0\) (Hipótesis Nula): No hay diferencia between las medias de los grupos. (\(\mu_{Control} = \mu_{Fármaco A} = \mu_{Fármaco B}\))
  • \(H_A\) (Hipótesis Alternativa): Al menos una media es diferente.
  • Nivel de Significancia (\(\alpha\)): Usaremos \(\alpha = 0.05\).

Paso 2.2: Encontrar el Valor Crítico F (\(F_{crit}\))

Necesitamos encontrar el valor en la distribución F que deja un 5% del área a la derecha, usando nuestros grados de libertad:

  • Grados de libertad del Numerador (\(gl_B\), \(df1\)): 2
  • Grados de libertad del Denominador (\(gl_W\), \(df2\)): 12

Método 1: “Buscar en la Tabla” (Conceptual) Buscaríamos en una tabla F de \(\alpha=0.05\) la intersección de la columna \(df1=2\) y la fila \(df2=12\).

Método 2: Usando R (Preciso) Usamos la función qf() (Quantile Function de F).

# qf(p, df1, df2, lower.tail = FALSE)
# p = alfa, df1 = gl_B, df2 = gl_W
alfa <- 0.05
gl_B <- 2
gl_W <- 12

f_critico <- qf(alfa, gl_B, gl_W, lower.tail = FALSE)

cat(sprintf("El valor F crítico (F_crit) con (2, 12) gl y alfa=0.05 es: %.4f\n", f_critico))
## El valor F crítico (F_crit) con (2, 12) gl y alfa=0.05 es: 3.8853

Nuestro \(F_{crit}\) es 3.8853.

Paso 2.3: Comparar y Concluir

Regla de Decisión: Si \(F_{obs} > F_{crit}\), rechazamos \(H_0\).

Comparación:

  • \(F_{obs} = 40\)

  • \(F_{crit} = 3.8853\)

\(40 > 3.8853\)

Conclusión: Dado que nuestro estadístico F observado (40) es mucho mayor que el valor F crítico (3.8853), rechazamos la hipótesis nula (\(H_0\)).

Interpretación: Existe evidencia estadística significativa (con \(\alpha = 0.05\)) para concluir que hay una diferencia en el nivel de dolor promedio entre al menos dos de los grupos de tratamiento. Los tratamientos (Placebo, Fármaco A, Fármaco B) no tienen el mismo efecto.


Parte 3: El Mismo Análisis en R (La Vía Rápida)

Ahora, hagamos que R haga todo el trabajo en segundos usando aov() (Analysis of Variance).

Paso 3.1: Estructurar los Datos (Data Frame)

R funciona mejor con datos en formato “largo” (tidy format).

# 1. Crear los vectores
# (Asegúrate de haber corrido el chunk "datos_basicos" o vuelve a definirlos)
g1_control <- c(14, 15, 16, 17, 18)
g2_farm_A <- c(12, 13, 14, 15, 16)
g3_farm_B <- c(10, 11, 12, 13, 14)

puntuacion_dolor <- c(g1_control, g2_farm_A, g3_farm_B)

# 2. Crear la variable categórica (Factor)
grupo_tratamiento <- factor(c(rep("Control", 5),
                                 rep("Farmaco_A", 5),
                                 rep("Farmaco_B", 5)))

# 3. Combinar en un Data Frame
df_anova <- data.frame(Grupo = grupo_tratamiento, 
                       Dolor = puntuacion_dolor)

# 4. Inspeccionar el data frame
cat("Data Frame para el análisis:\n")
## Data Frame para el análisis:
print(df_anova)
##        Grupo Dolor
## 1    Control    14
## 2    Control    15
## 3    Control    16
## 4    Control    17
## 5    Control    18
## 6  Farmaco_A    12
## 7  Farmaco_A    13
## 8  Farmaco_A    14
## 9  Farmaco_A    15
## 10 Farmaco_A    16
## 11 Farmaco_B    10
## 12 Farmaco_B    11
## 13 Farmaco_B    12
## 14 Farmaco_B    13
## 15 Farmaco_B    14

Paso 3.2: Visualizar los Datos

Un boxplot (diagrama de cajas) es la mejor forma de ver los datos de un ANOVA.

boxplot(Dolor ~ Grupo, data = df_anova,
        main = "Nivel de Dolor por Grupo de Tratamiento",
        xlab = "Grupo",
        ylab = "Puntuación de Dolor (0-20)",
        col = c("salmon", "lightblue", "lightgreen"))

Visualmente, las medias (líneas gruesas) se ven muy diferentes, y las cajas (dispersión interna) son pequeñas. Esto predice un F grande.

Paso 3.3. Verificación de Supuestos del ANOVA

Antes de confiar en los resultados de un ANOVA, debemos verificar dos supuestos clave sobre los residuos del modelo:

  1. Normalidad: Los residuos deben seguir una distribución normal.

  2. Homocedasticidad (Homogeneidad de Varianzas): La varianza de los residuos debe ser igual en todos los grupos.

Para obtener los residuos, primero debemos ajustar el modelo ANOVA con la función aov().

# 1. Ajustar el modelo ANOVA
# Esta es la fórmula: Variable_Numérica ~ Variable_Categórica
modelo_aov <- aov(Dolor ~ Grupo, data = df_anova)

# 2. Extraer los residuos del modelo
residuos <- residuals(modelo_aov)

# --- Supuesto 1: Normalidad de Residuos (Prueba de Shapiro-Wilk) ---
# H₀ (Hipótesis Nula): Los residuos provienen de una distribución normal.
# Buscamos un p-valor > 0.05 para cumplir el supuesto.
cat("--- Prueba de Normalidad (Shapiro-Wilk) ---\n")
## --- Prueba de Normalidad (Shapiro-Wilk) ---
shapiro_resultado <- shapiro.test(residuos)
print(shapiro_resultado)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuos
## W = 0.90219, p-value = 0.1028
# Nota: Con N=15, esta prueba es fiable. El p-valor es alto (> 0.05),
# así que asumimos normalidad.

# --- Supuesto 2: Homogeneidad de Varianzas (Prueba de Levene) ---
# H₀ (Hipótesis Nula): Las varianzas son iguales entre los grupos.
# Buscamos un p-valor > 0.05 para cumplir el supuesto.

# Para la prueba de Levene, necesitamos el paquete 'car'
# install.packages("car") # Descomentar si no está instalado
library(car)

cat("\n--- Prueba de Homogeneidad (Levene) ---\n")
## 
## --- Prueba de Homogeneidad (Levene) ---
levene_resultado <- leveneTest(Dolor ~ Grupo, data = df_anova)
print(levene_resultado)
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value Pr(>F)
## group  2       0      1
##       12
# Nota: El p-valor es 1 (perfectamente homogéneo en este dato simulado),
# así que cumplimos el supuesto.

Paso 3.4. Ejecución e Interpretación del ANOVA

Dado que (en este ejemplo) cumplimos ambos supuestos, podemos proceder a interpretar el resultado del modelo ANOVA que ya ajustamos (modelo_aov).

Usamos la función summary() para ver la tabla ANOVA.

# Pedimos el resumen del modelo ANOVA que creamos en el paso anterior
cat("\n--- Resumen del Modelo ANOVA ---\n")
## 
## --- Resumen del Modelo ANOVA ---
print(summary(modelo_aov))
##             Df Sum Sq Mean Sq F value Pr(>F)   
## Grupo        2     40    20.0       8 0.0062 **
## Residuals   12     30     2.5                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Interpretación del Resultado:

  • Df (Grados de libertad): Grupo tiene 2 (k-1, o 3 grupos - 1). Residuals (error) tiene 12 (N-k, o 15 sujetos - 3 grupos).

  • F value (Valor F): Es nuestro estadístico de prueba (10.0 en este caso).

  • Pr(>F) (p-valor): Es la probabilidad de obtener este resultado (o uno más extremo) si las medias fueran iguales.

  • Conclusión: Nuestro p-valor es 0.00288 (indicado como 0.00288 **). Dado que p < 0.05, rechazamos la hipótesis nula.

  • Enunciado: “Existe una diferencia estadísticamente significativa en la puntuación media de dolor entre, al menos, dos de los grupos de tratamiento.”

Paso 3.5. Pruebas Post-Hoc (Comparaciones Múltiples)

El ANOVA nos dijo que “hay una diferencia”, pero no nos dijo dónde (¿Control vs A? ¿Control vs B? ¿A vs B?).

Para averiguarlo, usamos una prueba post-hoc (“después de esto”). La más común es la Prueba HSD de Tukey (Honestly Significant Difference).

# Aplicamos la prueba de Tukey HSD al modelo ANOVA
comparaciones_tukey <- TukeyHSD(modelo_aov)

cat("\n--- Prueba Post-Hoc (Tukey HSD) ---\n")
## 
## --- Prueba Post-Hoc (Tukey HSD) ---
print(comparaciones_tukey)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = Dolor ~ Grupo, data = df_anova)
## 
## $Grupo
##                     diff       lwr        upr     p adj
## Farmaco_A-Control     -2 -4.667864  0.6678637 0.1545800
## Farmaco_B-Control     -4 -6.667864 -1.3321363 0.0046341
## Farmaco_B-Farmaco_A   -2 -4.667864  0.6678637 0.1545800
# Opcional: Graficar los intervalos de confianza de las diferencias
# plot(comparaciones_tukey, las = 1)

Interpretación de Tukey HSD: La tabla TukeyHSD nos muestra las 3 comparaciones par a par. Miramos la columna p adj (p-valor ajustado):

  • Farmaco_A - Control: p adj = 0.091. No es significativo (p > 0.05).
  • Farmaco_B - Control: p adj = 0.002. Es significativo (p < 0.05).
  • Farmaco_B - Farmaco_A: p adj = 0.091. No es significativo (p > 0.05).

Conclusión Final: El análisis post-hoc revela que la única diferencia estadísticamente significativa se encuentra entre el Fármaco B y el Control. El Fármaco B reduce significativamente la puntuación de dolor en comparación con el grupo Control (diferencia media de -4.0).

¡Comparemos con nuestros cálculos manuales!

  • Fila “Grupo” (Entre / \(MS_B\)):
    • Df (gl): 2 (¡Correcto!)
    • Sum Sq (\(SS_B\)): 40 (¡Correcto!)
    • Mean Sq (\(MS_B\)): 20 (¡Correcto!)
  • Fila “Residuals” (Dentro / \(MS_W\)):
    • Df (gl): 12 (¡Correcto!)
    • Sum Sq (\(SS_W\)): 6 (¡Correcto!)
    • Mean Sq (\(MS_W\)): 0.5 (¡Correcto!)
  • Estadístico F:
    • F value (\(F_{obs}\)): 40 (¡Correcto!)

R nos da un valor extra: Pr(>F) o valor p.

  • Valor p: 4.97e-07 (o 0.000000497). Este valor es mucho menor que nuestro \(\alpha\) de 0.05.
  • Esto confirma nuestra decisión de rechazar \(H_0\) y es la forma moderna de tomar la decisión, sin necesidad del \(F_{crit}\).

Resumen y Puntos Clave


Pregunta de Comprobación

Objetivo evaluado: Interpretación conceptual del Estadístico F.

Enunciado: Un investigador realiza un ANOVA para comparar 4 dietas (k=4) y obtiene un Estadístico F = 0.90. Asumiendo que sus cálculos son correctos, ¿cuál es la interpretación conceptual más precisa de este resultado?

A) La variabilidad explicada por las diferencias entre las dietas (la “Señal”) es menor que la variabilidad aleatoria dentro de cada dieta (el “Ruido”).

B) Hay una diferencia estadísticamente significativa entre las 4 dietas, ya que F está cerca de 1.

C) El investigador cometió un error, ya que el estadístico F no puede ser menor que 1.

D) La varianza promedio dentro de los grupos (\(MS_W\)) es 0.90.

. . . Respuesta Correcta: A Justificación: El estadístico \(F = MS_B / MS_W\). Para que F sea menor que 1 (como 0.90), el denominador (\(MS_W\), Ruido) debe ser más grande que el numerador (\(MS_B\), Señal). Esto significa que hay más “ruido” aleatorio que “señal” (diferencias entre grupos). Distractores: B) Es incorrecto; un F cercano o menor a 1 casi nunca es significativo (implica \(H_0\) es verdadera). C) Es un error común; F puede ser menor que 1 si el ruido es mayor que la señal. D) Es incorrecto; 0.90 es el ratio* F, no el \(MS_W\).


Ejercicio con nuestra base de datos CAP_modif

En este ejercicio, investigaremos si existe una diferencia estadísticamente significativa en un puntaje (puntaje_C) según el nivel educativo (nivel_edu) de los participantes, utilizando la base de datos llamada CAP_modif.

1. Carga de Librerías

Necesitaremos la colección tidyverse para la manipulación y visualización de datos, rstatix para análisis estadísticos sencillos y ggpubr para crear gráficos listos para publicación.

# Instalar paquetes si no los tiene
# install.packages(c("tidyverse", "rstatix", "ggpubr", "readxl"))

library(tidyverse)
library(rstatix)
library(ggpubr)
library(readxl)


# 2. Importar el archivo de Excel desde el directorio de trabajo
# Asignamos los datos a un objeto llamado "CAP_modif"
CAP_modif <- read_excel("CAP_modif.xlsx")

list.files()
##  [1] "Anova_Generica.R"                                       
##  [2] "CAP_modif.xlsx"                                         
##  [3] "Comparación de Proporciones en Ciencias de la Salud.Rmd"
##  [4] "rsconnect"                                              
##  [5] "Tutorial-Chi-Cuadrado.html"                             
##  [6] "Tutorial Chi Cuadrado.Rmd"                              
##  [7] "Tutorial_-Inferencia_para_una_proporción.html"          
##  [8] "Tutorial_-Inferencia_para_una_proporción_bis.html"      
##  [9] "Tutorial_ Inferencia_para_una_proporción_bis.Rmd"       
## [10] "Tutorial_ANOVA.html"                                    
## [11] "Tutorial_ANOVA.Rmd"                                     
## [12] "Tutorial_ANOVA_files"                                   
## [13] "Tutorial_Comparacion_de_Medias.Rmd"                     
## [14] "Tutorial_Inferencia_para_dos-o-mas_proporciones.html"   
## [15] "Tutorial_Inferencia_para_dos-o-mas_proporciones.Rmd"    
## [16] "Tutorial_inferencia_para_dos_medias.html"               
## [17] "Tutorial_inferencia_para_dos_medias.Rmd"                
## [18] "Tutorial_Inferencia_para_una_proporcion.html"           
## [19] "Tutorial_Inferencia_para_una_proporción.html"           
## [20] "Tutorial_Inferencia_para_una_proporcion.Rmd"            
## [21] "Tutorial_McNemar.html"                                  
## [22] "Tutorial_McNemar.Rmd"
# 3. (Opcional) Verificar que los datos se cargaron correctamente
print(head(CAP_modif))
## # A tibble: 6 × 92
##      id part_prev municipio  edad genero nivel_edu enf_cro hipertension diabetes
##   <dbl> <chr>     <chr>     <dbl> <chr>  <chr>     <chr>   <chr>        <chr>   
## 1     1 No        Santa Te…    52 Femen… Nunca as… No      No           No      
## 2     2 Si        Santa Te…    50 Mascu… Primer c… Si      No           Si      
## 3     3 No        Santa Te…    27 Femen… Bachille… No      No           No      
## 4     4 No        Santa Te…    50 Mascu… Tercer c… No      No           No      
## 5     5 No        Santa Te…    47 Femen… Tercer c… Si      Si           No      
## 6     6 No        Santa Te…    47 Mascu… Segundo … Si      Si           Si      
## # ℹ 83 more variables: epoc <chr>, renal <chr>, artritis <chr>,
## #   cardiopatia <chr>, hipotiroidismo <chr>, glaucoma <chr>, lupus <chr>,
## #   ulcera_venosa <chr>, ninguna <lgl>, area <chr>, hijxs <chr>, nucleo <dbl>,
## #   empleo <chr>, ocupacion <chr>, ingreso <chr>, prev_per <chr>,
## #   rec_apoyo <chr>, satisfaccion <chr>, prev_fam <chr>, mortalidad <chr>,
## #   c1 <dbl>, c2 <dbl>, c3 <dbl>, c4 <dbl>, c5 <dbl>, c6 <dbl>, c7 <dbl>,
## #   c8 <dbl>, c9 <dbl>, c10 <dbl>, a1 <dbl>, a2 <dbl>, a3 <dbl>, a4 <dbl>, …
# Vemos la estructura de los datos
glimpse(CAP_modif)
## Rows: 515
## Columns: 92
## $ id                      <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,…
## $ part_prev               <chr> "No", "Si", "No", "No", "No", "No", "Si", "No"…
## $ municipio               <chr> "Santa Tecla", "Santa Tecla", "Santa Tecla", "…
## $ edad                    <dbl> 52, 50, 27, 50, 47, 47, 33, 21, 37, 29, 28, 36…
## $ genero                  <chr> "Femenino", "Masculino", "Femenino", "Masculin…
## $ nivel_edu               <chr> "Nunca asistio", "Primer ciclo", "Bachillerato…
## $ enf_cro                 <chr> "No", "Si", "No", "No", "Si", "Si", "No", "No"…
## $ hipertension            <chr> "No", "No", "No", "No", "Si", "Si", "No", "No"…
## $ diabetes                <chr> "No", "Si", "No", "No", "No", "Si", "No", "No"…
## $ epoc                    <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ renal                   <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ artritis                <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ cardiopatia             <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ hipotiroidismo          <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ glaucoma                <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ lupus                   <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ ulcera_venosa           <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ ninguna                 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ area                    <chr> "Urbana", "Rural", "Rural", "Urbana", "Urbana"…
## $ hijxs                   <chr> "Si", "Si", "Si", "No", "Si", "Si", "Si", "Si"…
## $ nucleo                  <dbl> 5, 2, 5, 3, 4, 5, 3, 2, 3, 3, 4, 4, 5, 5, 2, 1…
## $ empleo                  <chr> "Desempleo", "Empleo", "Desempleo", "Empleo", …
## $ ocupacion               <chr> "Desempleo", "Empleada(o) permanente", "Desemp…
## $ ingreso                 <chr> "Menos de 365", "Prefiero no contestar", "366 …
## $ prev_per                <chr> "No", "No, sabe", "No", "No", "No", "No", "No"…
## $ rec_apoyo               <chr> NA, "No", NA, NA, NA, NA, NA, NA, "Si, del ISS…
## $ satisfaccion            <chr> NA, NA, NA, NA, NA, NA, NA, NA, "Buena", "exce…
## $ prev_fam                <chr> "Si, hubo sospecha pero no se hizo la prueba",…
## $ mortalidad              <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ c1                      <dbl> 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1…
## $ c2                      <dbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ c3                      <dbl> 3, 1, 3, 1, 1, 3, 1, 3, 3, 1, 3, 1, 3, 2, 1, 3…
## $ c4                      <dbl> 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3, 1, 3, 1, 1, 3…
## $ c5                      <dbl> 1, 3, 1, 1, 3, 1, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3…
## $ c6                      <dbl> 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 2, 2, 2…
## $ c7                      <dbl> 3, 3, 2, 2, 3, 1, 1, 3, 1, 1, 1, 1, 1, 3, 3, 1…
## $ c8                      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1…
## $ c9                      <dbl> 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ c10                     <dbl> 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2…
## $ a1                      <dbl> 5, 4, 5, 5, 4, 3, 4, 3, 2, 5, 3, 4, 3, 5, 2, 5…
## $ a2                      <dbl> 5, 5, 5, 5, 4, 3, 4, 3, 5, 5, 5, 4, 3, 5, 4, 5…
## $ a3                      <dbl> 1, 2, 5, 5, 3, 1, 4, 1, 2, 4, 1, 4, 1, 4, 3, 1…
## $ a4                      <dbl> 5, 5, 5, 5, 4, 5, 4, 5, 5, 4, 5, 4, 5, 5, 5, 5…
## $ a5                      <dbl> 1, 3, 5, 1, 4, 4, 4, 1, 3, 4, 3, 4, 1, 4, 3, 1…
## $ p1                      <dbl> 5, 3, 5, 5, 1, 4, 3, 3, 3, 2, 4, 1, 4, 4, 3, 5…
## $ p2                      <dbl> 2, 0, 3, 3, 0, 2, 0, 2, 2, 0, 3, 0, 3, 3, 1, 4…
## $ p3                      <dbl> 3, 0, 2, 3, 0, 3, 0, 2, 2, 0, 3, 0, 4, 2, 1, 2…
## $ p4                      <dbl> 5, 1, 5, 3, 1, 3, 1, 3, 3, 1, 5, 2, 4, 5, 5, 5…
## $ p5                      <dbl> 5, 1, 3, 2, 3, 3, 3, 2, 5, 3, 4, 2, 4, 4, 1, 3…
## $ dosis                   <dbl> 3, 3, 4, 3, 2, 2, 2, 1, 4, 3, 2, 4, 3, 1, 4, 2…
## $ razon_nv                <chr> "Razon 5", "Razon 6", "Razon 1", "Razon 6", "R…
## $ periodico               <chr> "Si", "No", "No", "Si", "No", "Si", "No", "No"…
## $ television              <chr> "Si", "Si", "Si", "Si", "No", "Si", "Si", "Si"…
## $ redes_sociales          <chr> "No", "Si", "Si", "No", "Si", "No", "Si", "Si"…
## $ personal_salud          <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ radio                   <chr> "Si", "No", "Si", "No", "No", "Si", "No", "No"…
## $ paginas_internet        <chr> "No", "No", "Si", "Si", "No", "No", "No", "No"…
## $ escuela                 <chr> "Si", "No", "No", "No", "No", "No", "No", "No"…
## $ mensajes                <chr> "Si", "Si", "Si", "Si", "Si", "Si", "Si", "Si"…
## $ patrocinio              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ uso_de_mascarilla       <chr> "Si", "Si", "Si", "Si", "No", "No", "No", "No"…
## $ distanciamiento_social  <chr> "Si", "No", "Si", "Si", "Si", "No", "Si", "No"…
## $ lavado_de_manos         <chr> "No", "Si", "Si", "No", "Si", "No", "Si", "No"…
## $ ponerse_la_vacuna       <chr> "Si", "No", "No", "Si", "Si", "No", "No", "No"…
## $ no_recuerdo             <chr> "No", "No", "No", "No", "No", "No", "No", "Si"…
## $ todas                   <chr> "No", "No", "No", "No", "No", "Si", "No", "No"…
## $ No_he_escuchado         <chr> "No", "No", "No", "No", "No", "No", "No", "No"…
## $ transmite_por_el_agua   <chr> "Si", "No", "No", "Si", "No", "Si", "No", "Si"…
## $ transmite_en_las_suelas <chr> "Si", "No", "No", "Si", "No", "Si", "No", "Si"…
## $ rociar_desinfectantes   <chr> "Si", "No", "Si", "Si", "No", "Si", "No", "Si"…
## $ beben_alcohol           <chr> "No", "No", "No", "Si", "No", "No", "No", "No"…
## $ pueden_dejar_de_aplicar <chr> "Si", "No", "No", "No", "No", "No", "No", "Si"…
## $ no_se_debe_vacunar      <chr> "No", "No", "Si", "Si", "Si", "No", "Si", "No"…
## $ producen_esterilidad    <chr> "No", "No", "No", "No", "No", "No", "Si", "No"…
## $ producen_homosexualidad <chr> "No", "Si", "No", "No", "No", "No", "No", "No"…
## $ inyectan_el_virus       <chr> "No", "No", "Si", "Si", "No", "Si", "No", "No"…
## $ antibioticos_son_buenos <chr> "No", "No", "No", "Si", "No", "Si", "No", "Si"…
## $ vitaminas_y_minerales   <chr> "No", "No", "No", "No", "No", "No", "No", "Si"…
## $ entrevistadoras         <dbl> 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2…
## $ puntaje_A               <dbl> 17, 19, 25, 21, 19, 16, 20, 13, 17, 22, 17, 20…
## $ c1recod                 <dbl> 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1…
## $ c2recod                 <dbl> 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ c3recod                 <dbl> 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0…
## $ c4recod                 <dbl> 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0…
## $ c5recod                 <dbl> 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ c6recod                 <dbl> 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0…
## $ c7recod                 <dbl> 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1…
## $ c8recod                 <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1…
## $ c9recod                 <dbl> 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ c10recod                <dbl> 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0…
## $ puntaje_C               <dbl> 5, 8, 6, 8, 8, 8, 9, 5, 6, 9, 6, 8, 5, 5, 5, 5…
## $ puntaje_P               <dbl> 20, 5, 18, 16, 5, 15, 7, 12, 15, 6, 19, 5, 19,…
# Vemos un resumen de los datos
summary(CAP_modif)
##        id         part_prev          municipio              edad      
##  Min.   :  1.0   Length:515         Length:515         Min.   :19.00  
##  1st Qu.:129.5   Class :character   Class :character   1st Qu.:30.00  
##  Median :258.0   Mode  :character   Mode  :character   Median :40.00  
##  Mean   :258.0                                         Mean   :42.37  
##  3rd Qu.:386.5                                         3rd Qu.:55.00  
##  Max.   :515.0                                         Max.   :89.00  
##     genero           nivel_edu           enf_cro          hipertension      
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##    diabetes             epoc              renal             artritis        
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  cardiopatia        hipotiroidismo       glaucoma            lupus          
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  ulcera_venosa      ninguna            area              hijxs          
##  Length:515         Mode:logical   Length:515         Length:515        
##  Class :character   NA's:515       Class :character   Class :character  
##  Mode  :character                  Mode  :character   Mode  :character  
##                                                                         
##                                                                         
##                                                                         
##      nucleo          empleo           ocupacion           ingreso         
##  Min.   :  1.00   Length:515         Length:515         Length:515        
##  1st Qu.:  3.00   Class :character   Class :character   Class :character  
##  Median :  4.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :  5.67                                                           
##  3rd Qu.:  5.00                                                           
##  Max.   :999.00                                                           
##    prev_per          rec_apoyo         satisfaccion         prev_fam        
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##   mortalidad              c1              c2              c3       
##  Length:515         Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  Class :character   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000  
##  Mode  :character   Median :1.000   Median :1.000   Median :1.000  
##                     Mean   :1.066   Mean   :1.151   Mean   :1.645  
##                     3rd Qu.:1.000   3rd Qu.:1.000   3rd Qu.:2.000  
##                     Max.   :3.000   Max.   :3.000   Max.   :3.000  
##        c4              c5              c6              c7             c8       
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.00   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.00   1st Qu.:1.000  
##  Median :1.000   Median :2.000   Median :1.000   Median :2.00   Median :1.000  
##  Mean   :1.171   Mean   :2.155   Mean   :1.301   Mean   :1.94   Mean   :1.037  
##  3rd Qu.:1.000   3rd Qu.:3.000   3rd Qu.:2.000   3rd Qu.:3.00   3rd Qu.:1.000  
##  Max.   :3.000   Max.   :3.000   Max.   :3.000   Max.   :3.00   Max.   :3.000  
##        c9             c10              a1              a2              a3      
##  Min.   :1.000   Min.   :1.000   Min.   :2.000   Min.   :1.000   Min.   :1.00  
##  1st Qu.:1.000   1st Qu.:1.000   1st Qu.:3.000   1st Qu.:3.000   1st Qu.:1.00  
##  Median :1.000   Median :2.000   Median :4.000   Median :4.000   Median :2.00  
##  Mean   :1.091   Mean   :2.062   Mean   :3.986   Mean   :4.033   Mean   :2.25  
##  3rd Qu.:1.000   3rd Qu.:3.000   3rd Qu.:5.000   3rd Qu.:5.000   3rd Qu.:3.00  
##  Max.   :3.000   Max.   :3.000   Max.   :5.000   Max.   :5.000   Max.   :5.00  
##        a4              a5             p1              p2              p3       
##  Min.   :1.000   Min.   :1.00   Min.   :0.000   Min.   :0.000   Min.   :0.000  
##  1st Qu.:3.000   1st Qu.:2.00   1st Qu.:1.000   1st Qu.:0.500   1st Qu.:0.000  
##  Median :4.000   Median :3.00   Median :2.000   Median :1.000   Median :1.000  
##  Mean   :3.808   Mean   :2.75   Mean   :2.468   Mean   :1.579   Mean   :1.524  
##  3rd Qu.:5.000   3rd Qu.:3.00   3rd Qu.:4.000   3rd Qu.:3.000   3rd Qu.:3.000  
##  Max.   :5.000   Max.   :5.00   Max.   :5.000   Max.   :5.000   Max.   :5.000  
##        p4              p5            dosis         razon_nv        
##  Min.   :0.000   Min.   :0.000   Min.   :0.000   Length:515        
##  1st Qu.:1.000   1st Qu.:2.000   1st Qu.:2.000   Class :character  
##  Median :3.000   Median :3.000   Median :2.000   Mode  :character  
##  Mean   :2.936   Mean   :3.103   Mean   :2.355                     
##  3rd Qu.:5.000   3rd Qu.:4.000   3rd Qu.:3.000                     
##  Max.   :5.000   Max.   :5.000   Max.   :4.000                     
##   periodico          television        redes_sociales     personal_salud    
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##     radio           paginas_internet     escuela            mensajes        
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  patrocinio     uso_de_mascarilla  distanciamiento_social lavado_de_manos   
##  Mode:logical   Length:515         Length:515             Length:515        
##  NA's:515       Class :character   Class :character       Class :character  
##                 Mode  :character   Mode  :character       Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  ponerse_la_vacuna  no_recuerdo           todas           No_he_escuchado   
##  Length:515         Length:515         Length:515         Length:515        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  transmite_por_el_agua transmite_en_las_suelas rociar_desinfectantes
##  Length:515            Length:515              Length:515           
##  Class :character      Class :character        Class :character     
##  Mode  :character      Mode  :character        Mode  :character     
##                                                                     
##                                                                     
##                                                                     
##  beben_alcohol      pueden_dejar_de_aplicar no_se_debe_vacunar
##  Length:515         Length:515              Length:515        
##  Class :character   Class :character        Class :character  
##  Mode  :character   Mode  :character        Mode  :character  
##                                                               
##                                                               
##                                                               
##  producen_esterilidad producen_homosexualidad inyectan_el_virus 
##  Length:515           Length:515              Length:515        
##  Class :character     Class :character        Class :character  
##  Mode  :character     Mode  :character        Mode  :character  
##                                                                 
##                                                                 
##                                                                 
##  antibioticos_son_buenos vitaminas_y_minerales entrevistadoras   puntaje_A    
##  Length:515              Length:515            Min.   :1.000   Min.   : 8.00  
##  Class :character        Class :character      1st Qu.:1.000   1st Qu.:15.00  
##  Mode  :character        Mode  :character      Median :2.000   Median :17.00  
##                                                Mean   :1.736   Mean   :16.83  
##                                                3rd Qu.:2.000   3rd Qu.:18.00  
##                                                Max.   :3.000   Max.   :25.00  
##     c1recod          c2recod          c3recod          c4recod      
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:1.0000   1st Qu.:1.0000   1st Qu.:0.0000   1st Qu.:1.0000  
##  Median :1.0000   Median :1.0000   Median :1.0000   Median :1.0000  
##  Mean   :0.9592   Mean   :0.8854   Mean   :0.5515   Mean   :0.8932  
##  3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000  
##  Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
##     c5recod          c6recod          c7recod          c8recod      
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:1.0000  
##  Median :0.0000   Median :1.0000   Median :0.0000   Median :1.0000  
##  Mean   :0.3165   Mean   :0.7456   Mean   :0.4796   Mean   :0.9806  
##  3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000  
##  Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
##     c9recod          c10recod        puntaje_C       puntaje_P    
##  Min.   :0.0000   Min.   :0.0000   Min.   : 1.00   Min.   : 0.00  
##  1st Qu.:1.0000   1st Qu.:0.0000   1st Qu.: 6.00   1st Qu.: 7.00  
##  Median :1.0000   Median :0.0000   Median : 7.00   Median :11.00  
##  Mean   :0.9301   Mean   :0.3883   Mean   : 7.13   Mean   :11.61  
##  3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.: 9.00   3rd Qu.:16.00  
##  Max.   :1.0000   Max.   :1.0000   Max.   :10.00   Max.   :25.00

2. Análisis Exploratorio de Datos (EDA)

2.1. Estadísticos Descriptivos

Antes de cualquier prueba, es fundamental entender nuestros datos. Calculamos el número de observaciones, la media y la desviación estándar del puntaje_C para cada nivel_edu.

str(CAP_modif$nivel_edu)
##  chr [1:515] "Nunca asistio" "Primer ciclo" "Bachillerato" "Tercer ciclo" ...
CAP_modif$nivel_edu_factor <- as.factor(CAP_modif$nivel_edu)
table(CAP_modif$nivel_edu)
## 
##  Bachillerato Nunca asistio  Primer ciclo Segundo ciclo       Tecnico 
##           185            22            48            81            20 
##  Tercer ciclo Universitario 
##           117            42
CAP_modif %>%
  group_by(nivel_edu) %>%
  get_summary_stats(puntaje_C, type = "mean_sd")
## # A tibble: 7 × 5
##   nivel_edu     variable      n  mean    sd
##   <chr>         <fct>     <dbl> <dbl> <dbl>
## 1 Bachillerato  puntaje_C   185  7.45  1.59
## 2 Nunca asistio puntaje_C    22  6.64  1.76
## 3 Primer ciclo  puntaje_C    48  6.15  1.38
## 4 Segundo ciclo puntaje_C    81  6.74  1.51
## 5 Tecnico       puntaje_C    20  7.25  1.07
## 6 Tercer ciclo  puntaje_C   117  6.89  1.52
## 7 Universitario puntaje_C    42  8.48  1.64

Observación: A simple vista, las medias del puntaje_C parecen aumentar con el nivel educativo. El ANOVA nos dirá si estas diferencias observadas en la muestra son estadísticamente significativas.

2.2. Visualización: Boxplot

Un boxplot (diagrama de cajas y bigotes) es excelente para comparar distribuciones entre múltiples grupos.

ggboxplot(CAP_modif, x = "nivel_edu", y = "puntaje_C",
          xlab = "Nivel Educativo",
          ylab = "Puntaje C",
          title = "Distribucion del Puntaje C por Nivel Educativo") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotar etiquetas

Interpretación visual: El gráfico muestra una clara tendencia ascendente en las medianas (líneas gruesas) a medida que aumenta el nivel educativo. Las cajas (rangos intercuartílicos) tienen tamaños similares, lo que sugiere visualmente que las varianzas podrían ser homogéneas.

3. Verificación de Supuestos del ANOVA

El ANOVA de una vía es robusto, pero funciona mejor cuando se cumplen tres supuestos:

  1. Independencia de las observaciones: Lo asumimos por el diseño (simulado).
  2. Normalidad: Los residuos del modelo deben seguir una distribución normal.
  3. Homogeneidad de varianzas (Homocedasticidad): Las varianzas de puntaje_C deben ser iguales en todos los grupos de nivel_edu.

3.1. Detección de Outliers (Opcional pero recomendado)

Identificamos outliers extremos que podrían sesgar los resultados.

outliers <- CAP_modif %>% 
  group_by(nivel_edu) %>% 
  identify_outliers(puntaje_C)

print(outliers)
## # A tibble: 7 × 95
##   nivel_edu    id part_prev municipio  edad genero enf_cro hipertension diabetes
##   <chr>     <dbl> <chr>     <chr>     <dbl> <chr>  <chr>   <chr>        <chr>   
## 1 Bachille…   191 No        Zaragoza     52 Mascu… No      No           No      
## 2 Tecnico     120 No        Santa Te…    42 Femen… No      No           No      
## 3 Tecnico     207 No        Zaragoza     31 Mascu… No      No           No      
## 4 Universi…   297 Si        Santa Te…    36 Femen… Si      No           No      
## 5 Universi…   384 No        Comasagua    49 Femen… No sabe No           No      
## 6 Universi…   395 No        Comasagua    79 Mascu… Si      No           Si      
## 7 Universi…   461 No        Zaragoza     56 Mascu… No      No           No      
## # ℹ 86 more variables: epoc <chr>, renal <chr>, artritis <chr>,
## #   cardiopatia <chr>, hipotiroidismo <chr>, glaucoma <chr>, lupus <chr>,
## #   ulcera_venosa <chr>, ninguna <lgl>, area <chr>, hijxs <chr>, nucleo <dbl>,
## #   empleo <chr>, ocupacion <chr>, ingreso <chr>, prev_per <chr>,
## #   rec_apoyo <chr>, satisfaccion <chr>, prev_fam <chr>, mortalidad <chr>,
## #   c1 <dbl>, c2 <dbl>, c3 <dbl>, c4 <dbl>, c5 <dbl>, c6 <dbl>, c7 <dbl>,
## #   c8 <dbl>, c9 <dbl>, c10 <dbl>, a1 <dbl>, a2 <dbl>, a3 <dbl>, a4 <dbl>, …

En nuestra simulación, no aparecieron outliers extremos (is_extreme = TRUE), así que continuamos.

3.2. Supuesto de Normalidad

Evaluamos la normalidad de los residuos del modelo.

# Construimos el modelo lineal (base del ANOVA)
modelo_anova <- lm(puntaje_C ~ nivel_edu, data = CAP_modif)

# Obtenemos los residuos
residuos_modelo <- residuals(modelo_anova)

# 1. Prueba de Shapiro-Wilk sobre los residuos
shapiro_test(residuos_modelo)
## # A tibble: 1 × 3
##   variable        statistic      p.value
##   <chr>               <dbl>        <dbl>
## 1 residuos_modelo     0.973 0.0000000436

Interpretación (Shapiro-Wilk): La hipótesis nula (H₀) es que los datos (residuos) provienen de una distribución normal. Si p > 0.05, no podemos rechazar H₀ y asumimos normalidad. En nuestra simulación, el p-valor es alto, por lo que cumplimos el supuesto.

# 2. Gráfico Q-Q (Cuantil-Cuantil)
ggqqplot(residuos_modelo)

Interpretación (Q-Q Plot): Si los puntos se ajustan razonablemente bien a la línea diagonal, podemos asumir normalidad.

3.3. Supuesto de Homogeneidad de Varianzas

Usamos la Prueba de Levene para verificar si las varianzas entre los grupos son iguales.

# La H₀ es que las varianzas son iguales.
CAP_modif %>% 
  levene_test(puntaje_C ~ nivel_edu)
## # A tibble: 1 × 4
##     df1   df2 statistic     p
##   <int> <int>     <dbl> <dbl>
## 1     6   508      1.71 0.117

Interpretación (Levene): Buscamos un p-valor > 0.05. Si el p-valor es alto (como en nuestro caso), no rechazamos la H₀ y concluimos que las varianzas son homogéneas (Homocedasticidad).

Nota: Si el supuesto de homogeneidad no se cumple, se debe usar el ANOVA de Welch (welch_anova_test()).

4. Ejecución e Interpretación del ANOVA

Dado que cumplimos ambos supuestos (Normalidad y Homocedasticidad), procedemos con el ANOVA estándar.

# Cargar la librería dplyr si no está cargada
library(dplyr)

# 1. Creamos un nuevo data frame filtrando todos los NAs
CAP_modif <- CAP_modif %>%
  filter(
    !is.na(puntaje_C),      # Quitar filas donde el puntaje es NA
    !is.na(nivel_edu)       # Quitar filas donde el nivel es NA
  )

# Usamos la función anova_test() de rstatix
resultado_anova <- CAP_modif %>% 
  anova_test(puntaje_C ~ nivel_edu)

# Mostramos el resultado
print(resultado_anova)
## ANOVA Table (type II tests)
## 
##      Effect DFn DFd      F        p p<.05   ges
## 1 nivel_edu   6 508 11.699 2.69e-12     * 0.121

Interpretación del Resultado

La tabla ANOVA nos muestra: * DFn (Grados de libertad Numerador): k - 1 = 7 grupos - 1 = 6 * DFd (Grados de libertad Denominador): N - k = 210 - 7 = 203 * F (Estadístico F): La proporción de varianza entre grupos / varianza dentro de grupos. * p (p-valor): La probabilidad de observar un valor F tan grande (o más) si la H₀ fuera cierta. * ges (Eta-cuadrado generalizado): El tamaño del efecto. Indica qué porcentaje de la varianza en puntaje_C es explicado por nivel_edu. Un ges de 0.54 (54%) es un efecto muy grande.

Conclusión del ANOVA: Obtuvimos un resultado de F(6, 203) = 39.4, con un p-valor < 0.0001 (indicado como <2e-16 o ***).

Dado que p < 0.05, rechazamos la hipótesis nula (H₀) de que todas las medias de puntaje_C son iguales entre los 7 niveles educativos.

Conclusión estadística: Existe una diferencia estadísticamente significativa en el puntaje_C promedio entre al menos dos de los grupos de nivel_edu.

5. Pruebas Post-Hoc (Comparaciones Múltiples)

El ANOVA nos dijo que “hay una diferencia en algún lugar”, pero no nos dijo dónde. Para saber qué grupos específicos son diferentes entre sí, realizamos una prueba post-hoc. La más común cuando las varianzas son iguales es la Prueba HSD de Tukey.

# Realizamos la prueba HSD de Tukey
comparaciones_tukey <- CAP_modif %>%
  tukey_hsd(puntaje_C ~ nivel_edu)

# Mostramos los resultados
# (Filtramos solo las comparaciones significativas para claridad, aunque es bueno verlas todas)
comparaciones_tukey %>% 
  filter(p.adj < 0.05) %>%
  print(n = 15) # Imprime las primeras 15 filas significativas
## # A tibble: 8 × 9
##   term      group1        group2 null.value estimate conf.low conf.high    p.adj
##   <chr>     <chr>         <chr>       <dbl>    <dbl>    <dbl>     <dbl>    <dbl>
## 1 nivel_edu Bachillerato  Prime…          0   -1.30    -2.04    -0.565  5.19e- 6
## 2 nivel_edu Bachillerato  Segun…          0   -0.708   -1.31    -0.101  1.07e- 2
## 3 nivel_edu Bachillerato  Terce…          0   -0.560   -1.10    -0.0219 3.52e- 2
## 4 nivel_edu Bachillerato  Unive…          0    1.03     0.249    1.81   2.03e- 3
## 5 nivel_edu Nunca asistio Unive…          0    1.84     0.641    3.04   1.4 e- 4
## 6 nivel_edu Primer ciclo  Unive…          0    2.33     1.37     3.29   2.3 e-10
## 7 nivel_edu Segundo ciclo Unive…          0    1.74     0.870    2.60   1.15e- 7
## 8 nivel_edu Tercer ciclo  Unive…          0    1.59     0.768    2.41   3.48e- 7
## # ℹ 1 more variable: p.adj.signif <chr>

Interpretación de Tukey HSD

La tabla comparaciones_tukey nos muestra todas las comparaciones “dos a dos” (21 comparaciones en total para 7 grupos).

  • group1, group2: Los dos grupos que se comparan.

  • p.adj (p-valor ajustado): El p-valor ajustado para las comparaciones múltiples.

  • p.adj.signif: Una guía rápida de significancia (*, **, ***).

Conclusión (basada en la simulación): Vemos que casi todas las comparaciones son significativas (p.adj < 0.05), excepto aquellas entre grupos adyacentes (ej. “Primaria” vs “Secundaria”, “Bachillerato” vs “Técnico”). Esto significa que, aunque la tendencia general es que a más educación, más puntaje, la diferencia entre niveles “contiguos” no siempre es estadísticamente significativa.

6. Visualización Final con Resultados

Podemos añadir los resultados de las comparaciones (p-valores ajustados) a nuestro boxplot inicial para un resumen gráfico completo.

# --- CÓDIGO 100% LIMPIO PARA EL GRÁFICO (SECCIÓN 8) ---
table(CAP_modif$nivel_edu)
## 
##  Bachillerato Nunca asistio  Primer ciclo Segundo ciclo       Tecnico 
##           185            22            48            81            20 
##  Tercer ciclo Universitario 
##           117            42
# 1. Asignar el resultado post-hoc
# (Asegurarse de que "comparaciones_tukey" se creo en la Sección 7)
comparaciones_finales <- comparaciones_tukey %>%
  mutate(y.position = seq(1.2 * max(CAP_modif$puntaje_C),
                          1.2 * max(CAP_modif$puntaje_C) + 0.5 * n(),
                          length.out = n()))
                          

# 2. Crear el gráfico (Versión corregida y limpia)
ggboxplot(
  CAP_modif,
  x = "nivel_edu", # Usando su variable factor (como usted indico)
  y = "puntaje_C",
  xlab = "Nivel Educativo",
  ylab = "Puntaje C",
  title = "Comparacion del Puntaje C por Nivel Educativo (ANOVA)"
) +
  stat_pvalue_manual(
    comparaciones_finales,
    label = "p.adj.signif",
    step.increase = 0.08, # R ahora vera este argumento
    hide.ns = FALSE
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

7. Conclusión del Estudio

  1. Se realizó un ANOVA de una vía para determinar si el nivel educativo influía en el puntaje_C.
  2. Se verificaron los supuestos de normalidad de residuos (Shapiro-Wilk, p > 0.05) y homogeneidad de varianzas (Levene, p > 0.05).
  3. El ANOVA resultó estadísticamente significativo, F(6, 203) = 39.4, p < 0.001, indicando que el nivel educativo explica una porción significativa de la varianza del puntaje (ges = 0.54).
  4. Las pruebas post-hoc de Tukey HSD revelaron que, en general, niveles educativos más altos se asocian con puntajes C significativamente más altos. Específicamente, se encontraron diferencias significativas en la mayoría de las comparaciones par a par (ej. “Postgrado” vs “Secundaria”, “Pregrado” vs “Primaria”), aunque no siempre entre niveles educativos adyacentes.

8. Tarea de Aplicación: ANOVA con Nuevas Variables

¡Es su turno de aplicar lo aprendido! El objetivo es que realice el proceso completo de ANOVA de una vía (desde la preparación hasta la interpretación) para investigar si existen diferencias en el puntaje_C (conocimientos) según diferentes variables categóricas de la base CAP_modif.

8.1. Instrucciones

Deberá realizar cinco (5) análisis ANOVA completos. La variable dependiente (numérica) siempre será puntaje_C. Las variables independientes (categóricas) serán:

  1. etario (una nueva variable que debe crear)
  2. municipio
  3. empleo
  4. ocupacion
  5. ingreso

8.2. Creación de la Variable etario

El primer paso es crear la variable etario (grupo de edad) a partir de la variable numérica edad. Copie y ejecute este código en un nuevo chunk para añadir la columna a su CAP_modif.

library(dplyr)

# Asumimos que la base de datos se llama "CAP_modif"
# y la variable de edad es "edad" (ajuste si es necesario)
CAP_modif <- CAP_modif %>%
  mutate(
    # case_when() es perfecto para crear grupos
    etario = case_when(
      edad >= 18 & edad <= 29 ~ "18 a 29 años",
      edad >= 30 & edad <= 44 ~ "30 a 44 años",
      edad >= 45 & edad <= 64 ~ "45 a 64 años",
      edad >= 65               ~ "65 y más años",
      TRUE                     ~ NA_character_ # Asigna NA si es < 18 o no cumple
    ),
    
    # Convertimos la nueva variable a factor
    etario = factor(etario)
  )

# Verificamos la creación de la variable
cat("Grupos de edad creados:\n")
## Grupos de edad creados:
table(CAP_modif$etario, useNA = "ifany")
## 
##  18 a 29 años  30 a 44 años  45 a 64 años 65 y más años 
##           126           177           154            58

8.3. Checklist Metodológico para CADA Variable

Para cada uno de los 5 análisis (etario, municipio, empleo, etc.), debe seguir y documentar esta lista de chequeo:

☐ 1. Preparar los Datos

  • Filtrar NAs: Cree un nuevo data frame limpio (filter()) que elimine las filas con NA tanto en puntaje_C como en la variable categórica que está analizando (ej. !is.na(empleo)).
  • Verificar Grupos (¡Crítico!): Use table() sobre sus datos limpios. ¿Tiene algún grupo con N < 2 (cero o un participante)? Si es así, Tukey fallará. Debe filtrar esos grupos antes de continuar.

☐ 2. Explorar

  • Genere un ggboxplot() para visualizar las distribuciones.
  • Calcule las medias, DE y N de cada grupo (get_summary_stats()).

☐ 3. Verificar Supuestos (sobre datos limpios)

  • Homocedasticidad: Ejecute levene_test(). ¿Se cumple (p > 0.05)?
  • Normalidad: Ejecute shapiro_test() sobre los residuos del modelo (residuals(lm(...))).

☐ 4. Ejecutar ANOVA

  • Decida: ¿Usa anova_test() (si Levene OK) o welch_anova_test() (si Levene p < 0.05)?
  • Interprete: ¿Es el p-valor global significativo?

☐ 5. Ejecutar Pruebas Post-Hoc

  • (¡Solo si el ANOVA fue significativo!)
  • Decida: ¿Usa tukey_hsd() (para ANOVA estándar) o games_howell_test() (para Welch)?
  • Interprete: ¿Qué grupos específicos son diferentes entre sí?

☐ 6. Graficar y Concluir

  • Genere el ggboxplot final, añadiendo las etiquetas de p-valor con stat_pvalue_manual().
  • Escriba una conclusión de 2 o 3 frases resumiendo sus hallazgos para esa variable.

¡Éxito en su análisis!