Antes de tomar decisiones, observamos la integridad de nuestra base de datos descargada de la nube.
glimpse(df_eda)
## Rows: 186
## Columns: 35
## $ id <fct> 0597e33c-bfcb-4cbb-ac47-a730f3f89270, 1…
## $ created_at <dttm> 2025-11-26 18:51:31, 2025-11-26 18:51:…
## $ demo_01_sexo <fct> Hombre, Mujer, Prefiero no indicar, Muj…
## $ demo_02_carrera <fct> Ingeniería Comercial, Medicina, Ingenie…
## $ demo_03_edad <int> 18, 19, 19, 18, 18, 20, 19, 18, 18, 19,…
## $ demo_04_semestre <ord> 2, 2, 3, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, …
## $ demo_05_escolaridad_padre <fct> Post-grado Universitario, Post-grado Un…
## $ demo_06_escolaridad_madre <fct> Post-grado Universitario, Post-grado Un…
## $ demo_07_ingresos <dbl> 20000, 10000, 30000, 6000, 20000, 22000…
## $ demo_08_afecta_economia <lgl> FALSE, TRUE, FALSE, FALSE, FALSE, FALSE…
## $ demo_09_trabaja <lgl> FALSE, FALSE, FALSE, TRUE, FALSE, FALSE…
## $ rend_01_promedio <dbl> 89.00, 90.00, 90.00, 91.00, 60.00, 80.0…
## $ rend_02_otra_carrera <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALS…
## $ rend_03_satisfecho <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRU…
## $ rend_04_materias_completas <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FAL…
## $ rend_05_beca <lgl> TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TR…
## $ uso_01_horas_dia <dbl> 4.0, 6.0, 2.0, 4.0, 4.0, 6.0, 2.0, 8.0,…
## $ uso_02_veces_revisa_clase <dbl> 4.0, 4.0, 2.0, 5.0, 6.0, 8.0, 3.0, 16.0…
## $ uso_03_llamadas <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FAL…
## $ uso_03_mensajes <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRU…
## $ uso_03_redes <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRU…
## $ uso_03_juegos <lgl> TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, F…
## $ uso_03_lectura <lgl> TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TR…
## $ uso_03_internet <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRU…
## $ uso_03_ia <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRU…
## $ uso_04_distraccion_redes <int> 1, 5, 1, 2, 5, 4, 3, 5, 1, 3, 2, 3, 2, …
## $ uso_05_pierde_hilo <int> 1, 4, 1, 1, 5, 4, 2, 5, 1, 2, 2, 3, 3, …
## $ uso_06_herramienta_acad <int> 5, 5, 1, 3, 4, 5, 3, 5, 1, 3, 5, 2, 5, …
## $ uso_07_revisar_vibracion <int> 1, 5, 1, 1, 3, 3, 2, 5, 1, 2, 2, 2, 1, …
## $ uso_08_necesidad_constante <lgl> TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, F…
## $ uso_09_ansiedad_bateria <lgl> TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FA…
## $ uso_10_uso_restringido <lgl> TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TR…
## $ uso_11_celular_cerca <lgl> TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, …
## $ uso_12_ansiedad_sin_celular <lgl> TRUE, FALSE, TRUE, FALSE, FALSE, FALSE,…
## $ uso_13_incomodidad_sin_celular <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FAL…
print(paste("Total de encuestas válidas:", nrow(df_eda)))
## [1] "Total de encuestas válidas: 186"
print(paste("Total de variables:", ncol(df_eda)))
## [1] "Total de variables: 35"
Verificamos si existen columnas vacías que puedan afectar el análisis estadístico.
# Gráfico de nulos
gg_miss_var(df_eda, show_pct = TRUE) +
labs(title = "Porcentaje de datos faltantes por variable", y = "% Faltante") +
theme_minimal()
Aquí identificamos valores extremos. Nota: No eliminaremos filas todavía, solo identificamos casos para decidir si aplicamos filtros en los modelos posteriores (ej: ANOVA o Regresión).
# Boxplot de Edad
p1 <- ggplot(df_eda, aes(y = demo_03_edad, x = "")) +
geom_boxplot(fill = "#F39C12", alpha = 0.7, outlier.colour = "red") +
labs(title = "Distribución Edad", y = "Años") + theme_minimal()
# Boxplot de Promedio
p2 <- ggplot(df_eda, aes(y = rend_01_promedio, x = "")) +
geom_boxplot(fill = "#3498DB", alpha = 0.7, outlier.colour = "red") +
labs(title = "Promedio Académico", y = "Nota (0-100)") + theme_minimal()
# Boxplot de Horas de Uso
p3 <- ggplot(df_eda, aes(y = uso_01_horas_dia, x = "")) +
geom_boxplot(fill = "#2ECC71", alpha = 0.7, outlier.colour = "red") +
labs(title = "Uso Celular (Horas/Día)", y = "Horas") + theme_minimal()
# Unir gráficos (requiere librería patchwork)
p1 + p2 + p3
Listamos los IDs de los casos que parecen errores o extremos para discutirlos en grupo.
# Casos con promedios dudosos (muy bajos o perfectos)
outliers_notas <- df_eda %>%
filter(rend_01_promedio < 10 | rend_01_promedio == 100) %>%
select(id, demo_02_carrera, rend_01_promedio)
print("Casos con notas extremas:")
## [1] "Casos con notas extremas:"
outliers_notas
# Casos con uso de celular excesivo (> 15 horas)
outliers_uso <- df_eda %>%
filter(uso_01_horas_dia > 15) %>%
select(id, demo_02_carrera, uso_01_horas_dia)
print("Casos con uso excesivo (>15h):")
## [1] "Casos con uso excesivo (>15h):"
outliers_uso
Vemos la composición de la muestra por carrera y semestre.
# Gráfico de barras por carrera
df_eda %>%
count(demo_02_carrera) %>%
mutate(demo_02_carrera = fct_reorder(demo_02_carrera, n)) %>%
ggplot(aes(x = n, y = demo_02_carrera)) +
geom_col(fill = "steelblue") +
geom_text(aes(label = n), hjust = -0.1) +
labs(title = "Participantes por Carrera", x = "Cantidad", y = NULL) +
theme_minimal()
Una vista rápida para ver qué variables numéricas se relacionan entre sí (ej: ¿A más horas de uso, menor promedio?).
# Seleccionar solo numéricas y quitar filas con NA para la correlación
df_num <- df_eda %>%
select(where(is.numeric)) %>%
select(-demo_07_ingresos) %>% # Excluimos ingresos temporalmente si tiene muchos NA o ceros
na.omit()
matriz_cor <- cor(df_num)
corrplot(matriz_cor, method = "color", type = "upper",
tl.col = "black", tl.cex = 0.7,
addCoef.col = "black", number.cex = 0.6, # Agregar números
title = "Mapa de Calor de Correlaciones", mar = c(0,0,1,0))
### Instrucciones para tu equipo: 1. Instalar librerías (el script lo
intenta hacer automático con
pacman, pero si falla, que
instalen install.packages("corrplot"),
patchwork, naniar). 2. Darle al botón
Knit (tejer) en RStudio. 3. Analizar el HTML resultante
para tomar decisiones sobre qué filtrar.
¡Este reporte les dará una base sólida para el ANOVA sin borrar datos a ciegas!