# Ajusta la ruta/hoja si cambia:
ruta <- "C:/Users/Quimica/Downloads/Rstudio Lerma/Diagnostico_Conalep_Lerma.xlsx"
hoja <- "Respuestas de formulario 1"
datos_raw <- read_excel(ruta, sheet = hoja)
datos <- datos_raw %>% janitor::clean_names()
# Para referencia:
names(datos)
## [1] "marca_temporal"
## [2] "x1_a_que_municipio_perteneces"
## [3] "x2_cual_es_tu_edad"
## [4] "x3_sexo_con_el_que_te_identificas"
## [5] "x4_como_te_sientes_al_iniciar_una_semana_escolar_explica_por_que"
## [6] "x5_describe_un_momento_reciente_en_el_que_te_hayas_sentido_muy_bien_o_muy_mal_dentro_de_la_escuela"
## [7] "x6_que_emociones_experimentas_cuando_piensas_en_tus_clases_o_tus_profesores"
## [8] "x7_que_es_lo_que_mas_te_preocupa_actualmente_en_tu_vida_escolar"
## [9] "x8_hay_algo_que_te_impida_concentrarte_o_rendir_como_te_gustaria_explica_9"
## [10] "x8_hay_algo_que_te_impida_concentrarte_o_rendir_como_te_gustaria_explica_10"
## [11] "que_piensas_o_sientes_cuando_tienes_muchos_trabajos_o_tareas_acumuladas"
## [12] "x11_como_manejas_los_nervios_o_la_ansiedad_antes_de_un_examen_importante"
## [13] "x12_que_te_motiva_a_seguir_estudiando_incluso_cuando_sientes_que_no_puedes_mas"
## [14] "x13_crees_que_tu_rendimiento_escolar_depende_de_tu_estado_emocional_por_que"
## [15] "x14_que_factores_crees_que_han_influido_en_tus_calificaciones_ultimamente"
## [16] "x15_como_describirias_tu_experiencia_con_el_ambiente_escolar_en_tu_grupo"
## [17] "x16_que_tanto_influye_tu_alimentacion_o_sueno_en_tu_forma_de_estudiar"
## [18] "x17_crees_que_tus_habitos_diarios_comida_descanso_tiempo_libre_afectan_tu_rendimiento_escolar_de_que_manera"
## [19] "x18_te_sientes_con_energia_suficiente_durante_el_dia_para_realizar_todas_tus_actividades_escolares_explica_por_que"
## [20] "x19_sueles_desayunar_antes_de_venir_a_la_escuela_explica_por_que_si_o_por_que_no"
## [21] "x20_que_tipo_de_alimentos_consumes_durante_tu_jornada_escolar_como_crees_que_influyen_en_tu_concentracion_o_energia"
## [22] "x21_has_notado_algun_cambio_en_tu_estado_de_animo_o_en_tu_rendimiento_escolar_cuando_no_te_alimentas_bien_describe_la_situacion"
## [23] "x22_con_que_frecuencia_consumes_alimentos_chatarra_o_bebidas_energeticas_durante_el_dia_escolar_crees_que_esto_te_afecta_en_tu_forma_de_estudiar"
## [24] "x23_consideras_que_una_mejor_alimentacion_podria_ayudarte_a_rendir_mejor_en_clase_o_sentirte_con_mas_energia_por_que"
## [25] "x24_con_que_frecuencia_evitas_usar_los_banos_escolares_durante_tu_jornada_escolar"
## [26] "x25_consideras_que_los_banos_escolares_estan_en_condiciones_adecuadas_de_limpieza_e_higiene"
## [27] "x26_alguna_vez_has_salido_del_aula_antes_o_despues_de_tiempo_por_problemas_relacionados_con_el_uso_del_bano"
## [28] "x27_como_describirias_tu_experiencia_al_utilizar_los_banos_escolares"
## [29] "x28_has_evitado_tomar_agua_concentrarte_o_participar_en_clase_por_no_querer_usar_los_banos_escolares_explica"
## [30] "x29_consideras_que_las_condiciones_de_los_banos_pueden_afectar_tu_rendimiento_academico_o_tu_bienestar_durante_la_jornada_escolar_por_que"
## [31] "x30_que_cambios_propondrias_para_mejorar_el_uso_y_la_higiene_de_los_banos_escolares_en_beneficio_del_alumnado"
## [32] "x31_que_red_social_usas"
## [33] "x32_describe_un_dia_tipico_en_el_que_uses_redes_sociales_cuantas_horas_les_dedicas_y_en_que_momentos_del_dia"
## [34] "x33_como_te_sientes_despues_de_pasar_mucho_tiempo_navegando_en_redes_sociales"
## [35] "x34_consideras_que_el_uso_de_redes_sociales_ha_afectado_tu_rendimiento_escolar_explica_como"
## [36] "x35_describe_una_situacion_en_la_que_las_redes_sociales_hayan_interferido_con_tus_tareas_o_examenes"
## [37] "x36_crees_que_podrias_mejorar_tu_desempeno_academico_si_cambiaras_tus_habitos_de_uso_de_redes_sociales_como"
## [38] "x37_cuantas_horas_sueles_dormir_por_noche_y_como_influye_el_uso_de_redes_sociales_en_tu_sueno"
## [39] "x38_te_ha_pasado_que_por_estar_en_redes_sociales_te_desveles_y_al_dia_siguiente_te_sientas_con_poca_energia_en_clase"
## [40] "x39_que_cambios_podrias_hacer_para_tener_un_mejor_descanso_nocturno_relacionado_con_el_uso_del_celular"
## [41] "x40_alguna_vez_has_tenido_conflictos_con_tu_familia_o_amigos_por_el_uso_de_redes_sociales_que_paso"
## [42] "x41_crees_que_el_uso_excesivo_de_redes_sociales_ha_influido_en_tus_relaciones_afectivas_o_de_amistad_de_que_manera"
## [43] "x42_como_equilibras_tu_tiempo_entre_redes_sociales_y_tus_relaciones_personales_cara_a_cara"
## [44] "x43_que_emociones_predominan_en_ti_mientras_navegas_en_redes_sociales_ansiedad_alegria_tristeza_etc_explica_con_ejemplos"
## [45] "x44_has_sentido_alguna_vez_dependencia_o_adiccion_hacia_alguna_red_social_como_lo_detectaste"
## [46] "x45_que_cambios_emocionales_has_notado_en_ti_cuando_reduces_o_suspendes_el_uso_de_redes_sociales"
## [47] "cuales_consideras_que_han_sido_los_motivos_principales_de_tus_reprobaciones"
## [48] "que_factores_personales_contribuyeron_a_tu_reprobacion_este_semestre"
## [49] "cual_era_la_causa_principal_por_la_que_faltabas_a_clases"
## [50] "que_propuestas_o_apoyos_consideras_que_podrian_ayudarte_a_evitar_la_reprobacion_o_el_ausentismo"
## [51] "que_semestre_eres"
## [52] "de_que_turno_eres"
## [53] "consideras_que_el_uso_de_redes_sociales_afecta_tu_rendimiento_academico"
nms <- names(datos)
# Columna de EDAD = "2. ¿Cuál es tu edad?"
# Tras clean_names suele quedar algo como "x2_cual_es_tu_edad"
col_edad <- nms[grepl("^x?2.*edad", nms, ignore.case = TRUE)]
# Columna de RIESGO (proxy) = "¿Consideras que el uso de redes sociales afecta tu rendimiento académico?"
# Suele quedar algo como "consideras_que_el_uso_de_redes_sociales_afecta_tu_rendimiento_academico"
col_riesgo <- nms[grepl("afecta.*rendimiento.*academico", nms, ignore.case = TRUE)]
if (length(col_edad) == 0) stop("No se encontró la columna de edad (buscando '^x?2.*edad').")
if (length(col_riesgo) == 0) stop("No se encontró la columna de riesgo (buscando 'afecta.*rendimiento.*academico').")
col_edad <- col_edad[1]
col_riesgo <- col_riesgo[1]
col_edad; col_riesgo
## [1] "x2_cual_es_tu_edad"
## [1] "x29_consideras_que_las_condiciones_de_los_banos_pueden_afectar_tu_rendimiento_academico_o_tu_bienestar_durante_la_jornada_escolar_por_que"
# Construir df con las columnas detectadas
df <- datos %>%
transmute(
edad_raw = .data[[col_edad]],
riesgo_raw = .data[[col_riesgo]]
)
# Intentar convertir edad a numérica
edad_num <- suppressWarnings(as.numeric(df$edad_raw))
if (all(is.na(edad_num))) {
# Caso: la edad ya viene como texto/rango (p. ej., "15-16")
edad_grupo <- trimws(as.character(df$edad_raw))
} else {
# Caso numérico: agrupar en rangos
edad_grupo <- cut(
edad_num,
breaks = c(-Inf, 16, 18, 20, Inf),
labels = c("15–16", "17–18", "19–20", "21+"),
right = TRUE
)
}
# Clasificar la respuesta de riesgo (Sí/No) en etiquetas claras
ries_fac <- df$riesgo_raw %>%
as.character() %>%
stringr::str_squish()
ries_fac_clas <- dplyr::case_when(
stringr::str_detect(stringr::str_to_lower(ries_fac), "\\bsí\\b|\\bsi\\b") ~ "Riesgo (sí afecta)",
stringr::str_detect(stringr::str_to_lower(ries_fac), "\\bno\\b") ~ "No riesgo (no afecta)",
TRUE ~ "NS/NR/Otro"
)
# Dataset final (limpio y con niveles ordenados)
final <- tibble::tibble(
edad_grupo = edad_grupo,
ries_fac = ries_fac_clas
) %>%
dplyr::filter(!is.na(edad_grupo), !is.na(ries_fac), edad_grupo != "", ries_fac != "")
final$edad_grupo <- factor(final$edad_grupo, levels = c("15–16","17–18","19–20","21+"))
final$ries_fac <- factor(final$ries_fac, levels = c("Riesgo (sí afecta)","No riesgo (no afecta)","NS/NR/Otro"))
# Chequeo rápido
dim(final)
## [1] 54 2
dplyr::count(final, edad_grupo)
## # A tibble: 4 × 2
## edad_grupo n
## <fct> <int>
## 1 15–16 29
## 2 17–18 16
## 3 19–20 6
## 4 21+ 3
dplyr::count(final, ries_fac)
## # A tibble: 3 × 2
## ries_fac n
## <fct> <int>
## 1 Riesgo (sí afecta) 11
## 2 No riesgo (no afecta) 39
## 3 NS/NR/Otro 4
tab3 <- table(final$edad_grupo, final$ries_fac)
prop3 <- prop.table(tab3, margin = 1) # proporción por grupo de edad
tab3
##
## Riesgo (sí afecta) No riesgo (no afecta) NS/NR/Otro
## 15–16 6 20 3
## 17–18 4 12 0
## 19–20 0 5 1
## 21+ 1 2 0
round(prop3, 3)
##
## Riesgo (sí afecta) No riesgo (no afecta) NS/NR/Otro
## 15–16 0.207 0.690 0.103
## 17–18 0.250 0.750 0.000
## 19–20 0.000 0.833 0.167
## 21+ 0.333 0.667 0.000
barplot(
t(as.matrix(prop3)),
beside = FALSE,
legend = TRUE,
args.legend = list(x = "topright", bty = "n", cex = 0.9),
main = "Proporción de 'afecta rendimiento' por grupo de edad",
xlab = "Grupo de edad",
ylab = "Proporción"
)
chi <- suppressWarnings(chisq.test(tab3))
chi
##
## Pearson's Chi-squared test
##
## data: tab3
## X-squared = 4.2542, df = 6, p-value = 0.6423
# Si hay frecuencias esperadas bajas, recomendar Fisher:
if (any(chi$expected < 5)) {
message("Hay celdas con frecuencias esperadas < 5; se sugiere Fisher exacto.")
print(fisher.test(tab3))
}
##
## Fisher's Exact Test for Count Data
##
## data: tab3
## p-value = 0.5988
## alternative hypothesis: two.sided
write.csv(as.data.frame(tab3), "tabla_frecuencias_edad_riesgo.csv", row.names = FALSE)
write.csv(as.data.frame(prop3), "tabla_proporciones_edad_riesgo.csv", row.names = FALSE)
## Diagnóstico rápido
# Qué valores trae realmente la columna de riesgo original:
cat("Valores únicos de riesgo_raw (primeros 20):\n")
## Valores únicos de riesgo_raw (primeros 20):
print(unique(head(df$riesgo_raw, 20)))
## [1] "no"
## [2] "No por qué no tienen nada que ver con el rendimiento académico"
## [3] "Si por que yo digo"
## [4] "No"
## [5] "No se."
## [6] "Si por cuestiones de salud"
## [7] "No están bien"
## [8] "Tal vez"
## [9] "Si porque es una necesidad"
## [10] "No mucho, por que evito tomar Agua para no estar saliendo"
## [11] "No por qué es muy diferente los baños s que algo académico"
## [12] "Si , deben estar limpios"
## [13] "No por que los baños y el estudio no hay nada que pueda relacionarse"
## [14] "No, porque eso es una necesidad y no algo con lo que puedas estudiar"
## [15] "No no afectan en nada."
## [16] "Solo el bienestar porque necesitan renovación ya que está muy viejos"
cat("\nFrecuencias de riesgo_raw:\n")
##
## Frecuencias de riesgo_raw:
print(table(df$riesgo_raw, useNA = "ifany"))
##
## Mi salud
## 1
## no
## 2
## No
## 18
## No , solo es rápido ir al baño
## 1
## No Creo que del Todo pero si en situaciones en donde eaten sucios
## 1
## No creo, porque afectarían no es como que nos vayamos a morir por usarlo
## 1
## No están bien
## 1
## No le veo mucho problema
## 1
## No mucho, por que evito tomar Agua para no estar saliendo
## 1
## No no afectan en nada.
## 1
## No por qué es muy diferente los baños s que algo académico
## 1
## No por que los baños y el estudio no hay nada que pueda relacionarse
## 1
## No por que no los utilizo con frecuencia
## 1
## No por qué no tienen nada que ver con el rendimiento académico
## 1
## No se
## 1
## No se.
## 1
## No ya que a nos ser que este enfermo
## 1
## No, es muy independiente aunque es importante
## 1
## No, eso no afecta en nada
## 1
## No, no le veo problema en este aspecto
## 1
## No, pero mi bienestar si, porque de esta manera puedo evitar enfermedades
## 1
## No, por que no tiene un afecto en consecuencia
## 1
## No, porque eso es una necesidad y no algo con lo que puedas estudiar
## 1
## Si , deben estar limpios
## 1
## Si por cuestiones de salud
## 1
## Si por qué evitamos el entrar mucho al los baños
## 1
## Si por qué hay vese que huelen feo
## 1
## Si por que yo digo
## 1
## Si porque es una necesidad
## 1
## Si, por qué tiene que tener más limpieza
## 1
## Si, porque se puede contraer una infección al lavarse las manos o pasar a algún escusado
## 1
## Solo el bienestar porque necesitan renovación ya que está muy viejos
## 1
## Solo necesita agua jabón papel decoración y mantenimiento y ya solo afecta poco cuando pues no vaz al baño y te aguantas por esos mismos factores
## 1
## Tal vez
## 1
## Tal vez porque me estresó cuando están sucios
## 1
## Tal vez sí porque pensaría en mis necesidades
## 1
cat("\nFrecuencias de ries_fac_clas (clasificación Sí/No/NS):\n")
##
## Frecuencias de ries_fac_clas (clasificación Sí/No/NS):
print(table(ries_fac_clas, useNA = "ifany"))
## ries_fac_clas
## No riesgo (no afecta) NS/NR/Otro Riesgo (sí afecta)
## 39 4 11
cat("\nFrecuencias de edad_grupo:\n")
##
## Frecuencias de edad_grupo:
print(table(edad_grupo, useNA = "ifany"))
## edad_grupo
## 15–16 17–18 19–20 21+
## 29 16 6 3
## Tablas bonitas y “forzadas”
if (!requireNamespace("knitr", quietly = TRUE)) {
install.packages("knitr")
}
# Frecuencias y proporciones:
tab3 <- table(final$edad_grupo, final$ries_fac)
prop3 <- prop.table(tab3, margin = 1)
# Si la tabla quedó vacía, avisamos:
if (length(tab3) == 0 || nrow(as.data.frame(tab3)) == 0) {
stop("La tabla de contingencia está vacía. Revisa la clasificación (¿hay 'Sí'/'No' en la col. de riesgo?).")
}
# Mostrar como kable para asegurar visualización en HTML
knitr::kable(as.data.frame(tab3), caption = "Tabla de frecuencias (Edad x Riesgo)")
Var1 | Var2 | Freq |
---|---|---|
15–16 | Riesgo (sí afecta) | 6 |
17–18 | Riesgo (sí afecta) | 4 |
19–20 | Riesgo (sí afecta) | 0 |
21+ | Riesgo (sí afecta) | 1 |
15–16 | No riesgo (no afecta) | 20 |
17–18 | No riesgo (no afecta) | 12 |
19–20 | No riesgo (no afecta) | 5 |
21+ | No riesgo (no afecta) | 2 |
15–16 | NS/NR/Otro | 3 |
17–18 | NS/NR/Otro | 0 |
19–20 | NS/NR/Otro | 1 |
21+ | NS/NR/Otro | 0 |
knitr::kable(round(100*prop3, 1), caption = "Proporciones por grupo de edad (%)")
Riesgo (sí afecta) | No riesgo (no afecta) | NS/NR/Otro | |
---|---|---|---|
15–16 | 20.7 | 69.0 | 10.3 |
17–18 | 25.0 | 75.0 | 0.0 |
19–20 | 0.0 | 83.3 | 16.7 |
21+ | 33.3 | 66.7 | 0.0 |
## Gráfico garantizado
# Si solo hay categoría 'NS/NR/Otro', el gráfico apilado será feo o vacío.
# Filtramos opcionalmente para mostrar solo Sí/No si existen:
niveles_validos <- intersect(colnames(prop3), c("Riesgo (sí afecta)", "No riesgo (no afecta)"))
prop_plot <- if (length(niveles_validos) >= 1) {
prop3[, niveles_validos, drop = FALSE]
} else {
prop3
}
if (ncol(prop_plot) == 0) {
plot.new()
title("Sin datos suficientes para graficar\n(Revisa las respuestas de riesgo)")
} else {
barplot(
t(as.matrix(prop_plot)),
beside = FALSE,
legend = TRUE,
args.legend = list(x = "topright", bty = "n", cex = 0.9),
main = "Proporción por grupo de edad",
xlab = "Grupo de edad",
ylab = "Proporción"
)
}
ries_fac_clas <- dplyr::case_when(
stringr::str_detect(stringr::str_to_lower(ries_fac), "\\bsí\\b|\\bsi\\b") ~ "Riesgo (sí afecta)",
stringr::str_detect(stringr::str_to_lower(ries_fac), "\\bno\\b") ~ "No riesgo (no afecta)",
stringr::str_detect(stringr::str_to_lower(ries_fac), "a veces|depende|tal vez|poco") ~ "NS/NR/Otro",
TRUE ~ "NS/NR/Otro"
)
# Gráfico de barras apiladas (conteos)
barplot(
t(as.matrix(tab3)),
beside = FALSE,
legend = TRUE,
args.legend = list(x = "topright", bty = "n", cex = 0.9),
main = "Distribución de respuestas por grupo de edad",
xlab = "Grupo de edad",
ylab = "Frecuencia (número de estudiantes)"
)
# Barras agrupadas (cada grupo de edad, categorías lado a lado)
barplot(
t(as.matrix(tab3)),
beside = TRUE,
legend = TRUE,
args.legend = list(x = "topright", bty = "n", cex = 0.9),
main = "Respuestas por grupo de edad",
xlab = "Grupo de edad",
ylab = "Frecuencia (número de estudiantes)"
)
# Conteo solo de edad
barplot(table(final$edad_grupo),
main = "Distribución de estudiantes por grupo de edad",
ylab = "Frecuencia",
xlab = "Grupo de edad")
# Conteo solo de riesgo
barplot(table(final$ries_fac),
main = "Distribución de estudiantes por nivel de riesgo",
ylab = "Frecuencia",
xlab = "Categoría de riesgo")
tab_general <- table(final$ries_fac)
barplot(tab_general,
col = "lightgray",
main = "Distribución de riesgo académico (general)",
ylab = "Frecuencia (número de estudiantes)",
xlab = "Categoría de riesgo")
# Añadir los conteos encima de cada barra
text(x = seq_along(tab_general),
y = tab_general,
labels = tab_general,
pos = 3)
tab_edad <- table(final$edad_grupo, final$ries_fac)
barplot(t(as.matrix(tab_edad)),
beside = TRUE,
legend = TRUE,
col = c("darkgray", "lightgray"),
main = "Riesgo académico por grupos de edad",
ylab = "Frecuencia",
xlab = "Grupo de edad")
# Etiquetas con los conteos
valores <- t(as.matrix(tab_edad))
bp <- barplot(valores, beside = TRUE, plot = FALSE)
text(x = bp, y = valores, labels = valores, pos = 3, cex = 0.8)
tab_sexo <- table(datos$x3_sexo_con_el_que_te_identificas, final$ries_fac)
barplot(t(as.matrix(tab_sexo)),
beside = TRUE,
legend = TRUE,
col = c("darkgray", "lightgray"),
main = "Riesgo académico por sexo",
ylab = "Frecuencia",
xlab = "Sexo")
# Etiquetas con los conteos
valores <- t(as.matrix(tab_sexo))
bp <- barplot(valores, beside = TRUE, plot = FALSE)
text(x = bp, y = valores, labels = valores, pos = 3, cex = 0.8)
# ----- CREAR VARIABLE BINARIA Y AJUSTAR EL MODELO
# 1) Variable dependiente binaria (1 = Riesgo (sí afecta), 0 = resto)
final$ries_bin <- ifelse(final$ries_fac == "Riesgo (sí afecta)", 1, 0)
# 2) Detectar columna de SEXO en 'datos' (ya con clean_names)
nms <- names(datos)
col_sexo_candidates <- nms[grepl("^x?3.*sexo", nms, ignore.case = TRUE)]
col_sexo <- if (length(col_sexo_candidates) > 0) col_sexo_candidates[1] else NA_character_
# 3) Si encontramos sexo, lo añadimos a 'final' alineado por fila
if (!is.na(col_sexo)) {
final$sexo <- as.factor(datos[[col_sexo]])
# eliminar niveles vacíos
final$sexo <- droplevels(final$sexo)
}
# 4) Ajustar el modelo logístico:
# - Si 'sexo' existe, lo incluimos; si no, solo edad_grupo
if ("sexo" %in% names(final)) {
fit <- glm(ries_bin ~ edad_grupo + sexo,
data = final,
family = binomial)
} else {
fit <- glm(ries_bin ~ edad_grupo,
data = final,
family = binomial)
}
# 5) Resumen rápido del modelo
summary(fit)
##
## Call:
## glm(formula = ries_bin ~ edad_grupo + sexo, family = binomial,
## data = final)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.9753 0.5403 -1.805 0.071 .
## edad_grupo17–18 0.0228 0.7661 0.030 0.976
## edad_grupo19–20 -17.3212 2614.2588 -0.007 0.995
## edad_grupo21+ 1.2571 1.4466 0.869 0.385
## sexoMasculino -0.9749 0.8854 -1.101 0.271
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 54.593 on 53 degrees of freedom
## Residual deviance: 50.037 on 49 degrees of freedom
## AIC: 60.037
##
## Number of Fisher Scoring iterations: 17
# 6) Comprobaciones útiles
cat("\nN observaciones en el modelo:", nobs(fit), "\n")
##
## N observaciones en el modelo: 54
cat("Coeficientes:\n"); print(coef(summary(fit)))
## Coeficientes:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.9753299 0.5402862 -1.805209590 0.07104189
## edad_grupo17–18 0.0227989 0.7661400 0.029758135 0.97625995
## edad_grupo19–20 -17.3212274 2614.2587775 -0.006625674 0.99471352
## edad_grupo21+ 1.2570675 1.4465989 0.868981362 0.38485733
## sexoMasculino -0.9748848 0.8854077 -1.101057521 0.27087162
par(mfrow = c(2, 2))
plot(fit)
par(mfrow = c(1, 1))
cd <- cooks.distance(fit)
plot(cd, type = "h", main = "Distancia de Cook", ylab = "Cook's distance")
abline(h = 4/nobs(fit), col = "red", lty = 2)
influyentes <- which(cd > 4/nobs(fit))
text(influyentes, cd[influyentes], labels = influyentes, pos = 3, col = "blue")
par(mfrow = c(2, 2))
plot(fit)
par(mfrow = c(1, 1)) # volver al modo normal
png("diagnosticos_fit.png", width = 900, height = 900)
par(mfrow = c(2, 2))
plot(fit)
par(mfrow = c(1, 1))
dev.off()
## png
## 2
plot(fit, which = 1) # Residuals vs Fitted
plot(fit, which = 2) # Normal Q-Q
plot(fit, which = 3) # Scale-Location
plot(fit, which = 4) # Residuals vs Leverage
# Sólo corre si existe un modelo
modelo_obj <- if (exists("fit")) fit else if (exists("modelo")) modelo else if (exists("m")) m else NULL
if (!is.null(modelo_obj)) {
n <- nobs(modelo_obj)
p <- length(coef(modelo_obj))
res_stud <- rstudent(modelo_obj)
hat_values <- hatvalues(modelo_obj)
cooks <- cooks.distance(modelo_obj)
thr_res <- 2
thr_cook <- 4 / n
thr_lev <- 2 * p / n
diag_df <- data.frame(
idx = seq_len(n),
res_student = res_stud,
leverage = hat_values,
cooks = cooks,
flag_res = abs(res_stud) > thr_res,
flag_cook = cooks > thr_cook,
flag_lev = hat_values > thr_lev
)
diag_df$flag_any <- with(diag_df, flag_res | flag_cook | flag_lev)
cat("Umbrales: |res| >", thr_res, ", Cook >", signif(thr_cook,3), ", leverage >", signif(thr_lev,3), "\n")
cat("Top Cook:\n"); print(head(diag_df[order(-diag_df$cooks), ], 10))
if (exists("final")) {
influyentes_detalle <- cbind(diag_df[diag_df$flag_any, ], final[diag_df$flag_any, , drop = FALSE])
write.csv(influyentes_detalle, "observaciones_influyentes_detalle.csv", row.names = FALSE)
cat("✅ Guardado: 'observaciones_influyentes_detalle.csv'\n")
}
} else {
cat("⚠️ No hay modelo ('fit'/'modelo'/'m'); se omite detección de influyentes.\n")
}
## Umbrales: |res| > 2 , Cook > 0.0741 , leverage > 0.185
## Top Cook:
## idx res_student leverage cooks flag_res flag_cook flag_lev flag_any
## 35 35 1.788078 0.33333333 0.30000000 FALSE TRUE TRUE TRUE
## 11 11 2.156856 0.06461187 0.10383077 TRUE TRUE FALSE TRUE
## 23 23 2.156856 0.06461187 0.10383077 TRUE TRUE FALSE TRUE
## 30 30 -1.030015 0.33333333 0.07500000 FALSE TRUE TRUE TRUE
## 38 38 -1.030015 0.33333333 0.07500000 FALSE TRUE TRUE TRUE
## 7 7 1.659339 0.07024159 0.04212725 FALSE FALSE FALSE FALSE
## 14 14 1.659339 0.07024159 0.04212725 FALSE FALSE FALSE FALSE
## 28 28 1.659339 0.07024159 0.04212725 FALSE FALSE FALSE FALSE
## 54 54 1.659339 0.07024159 0.04212725 FALSE FALSE FALSE FALSE
## 26 26 1.659516 0.05804391 0.03469810 FALSE FALSE FALSE FALSE
## ✅ Guardado: 'observaciones_influyentes_detalle.csv'
Estudio observacional, transversal y analítico aplicado al alumnado del CONALEP Lerma. Se encuestó a estudiantes de 2.º, 4.º y 6.º semestre, de ambos turnos.
Para asegurar representatividad se calculó el tamaño de muestra con la fórmula para población finita con 95 % de confianza y 5 % de error máximo admisible (asumiendo \(p=0.5\)). El resultado operativo fue N = 55 estudiantes.
\[ n = \frac{N z^2 p(1-p)}{e^2 (N-1) + z^2 p(1-p)}, \quad z=1.96,\; e=0.05,\; p=0.5 \]
Cuestionario de 53 preguntas (Google Forms) que cubre: experiencia formativa, dimensiones socioemocionales, preocupaciones, estrés, motivación, hábitos de alimentación y sueño, influencia de redes sociales, motivos de reprobación y datos sociodemográficos (edad, sexo, turno, semestre).
Aplicación en aula con autorización institucional y consentimiento informado. Participación voluntaria y anónima.
readxl
y estandarización de nombres
con janitor::clean_names()
.ries_bin = 1
si sí
afecta, 0
en otro caso.α = 0.05. Descriptivos en conteos (no porcentajes);
Ji-cuadrado/Fisher para edad_grupo × riesgo
; regresión
logística (ries_bin ~ edad_grupo
[+ sexo si disponible]);
diagnósticos (residuos, Q–Q, Scale–Location, leverage) y medidas de
influencia (Cook \(>4/n\), leverage
\(>2p/n\)).
Datos anónimos, uso académico y acceso restringido.
R (RStudio). Gráficos que requieren espacio se guardan a PNG con dimensiones fijas para evitar errores de render.