Analítica de Personas · Semestre otoño 2026 · Semana 3 · Referencia
Los modelos estadísticos en R (lm(), glm(), t.test(), etc.) devuelven objetos complejos con estructuras inconsistentes. broom los convierte en tibbles limpios y predecibles que puedes filtrar, graficar y exportar directamente.
summary(modelo)$coefficients
# Devuelve una matrix
# Columnas con nombres inconsistentes
# No incluye intervalos de confianza
# Los coeficientes están en log-odds
# No se puede usar con ggplot o dplyr
tidy(modelo, exponentiate = TRUE,
conf.int = TRUE)
# Devuelve un tibble
# Columnas estándar siempre iguales
# Con intervalos de confianza
# Odds ratios directos
# Se integra con ggplot y dplyr
library(broom)
# broom se instala automáticamente con tidyverse
# pero hay que cargarlo explícitamente
broom tiene tres funciones que se aplican a prácticamente cualquier modelo en R:
| Función | ¿Qué devuelve? | Una fila por... | Uso principal |
|---|---|---|---|
tidy() | Coeficientes del modelo | Cada variable/término | Tabla de odds ratios, forest plots |
glance() | Métricas globales del modelo | El modelo completo (1 fila) | Comparar modelos (AIC, BIC, deviance) |
augment() | Datos originales + predicciones | Cada observación | Diagnósticos, residuos, valores predichos |
modelo <- glm(rotacion_bin ~ satisfaccion_laboral + edad + antiguedad_anios,
data = innovaco, family = binomial)
# Coeficientes en log-odds (poco útil para comunicar)
tidy(modelo)
# # A tibble: 4 × 5
# term estimate std.error statistic p.value
# (Intercept) 1.234 0.456 2.707 0.0068
# satisfaccion_laboral -0.432 0.078 -5.538 3.1e-8
# edad -0.021 0.009 -2.333 0.0196
# antiguedad_anios -0.145 0.034 -4.265 2.0e-5
# ESTO es lo que quieres para comunicar resultados
tidy(modelo, exponentiate = TRUE, conf.int = TRUE)
# # A tibble: 4 × 7
# term estimate std.error statistic p.value conf.low conf.high
# (Intercept) 3.435 0.456 2.707 0.0068 1.405 8.397
# satisfaccion_laboral 0.649 0.078 -5.538 3.1e-8 0.557 0.757
# edad 0.979 0.009 -2.333 0.0196 0.961 0.997
# antiguedad_anios 0.865 0.034 -4.265 2.0e-5 0.809 0.925
| Columna | Contenido | Con exponentiate = TRUE |
|---|---|---|
term | Nombre de la variable | Igual |
estimate | Coeficiente (log-odds) | Odds ratio |
std.error | Error estándar | Error estándar (del log-OR) |
statistic | Estadístico z (Wald) | Igual |
p.value | P-valor | Igual |
conf.low | IC 95% inferior (log-odds) | IC 95% inferior del OR |
conf.high | IC 95% superior (log-odds) | IC 95% superior del OR |
# Solo los predictores significativos
tidy(modelo, exponentiate = TRUE, conf.int = TRUE) |>
filter(term != "(Intercept)",
p.value < 0.05)
# Ordenar por efecto (de mayor a menor OR)
tidy(modelo, exponentiate = TRUE, conf.int = TRUE) |>
filter(term != "(Intercept)") |>
arrange(desc(estimate))
# Crear etiquetas para el gráfico
tidy(modelo, exponentiate = TRUE, conf.int = TRUE) |>
filter(term != "(Intercept)") |>
mutate(
variable = case_when(
term == "satisfaccion_laboral" ~ "Satisfacción laboral",
term == "antiguedad_anios" ~ "Antigüedad (años)",
term == "edad" ~ "Edad",
TRUE ~ term
),
significativo = p.value < 0.05
)
# Forest plot de odds ratios (código completo)
or_datos <- tidy(modelo, exponentiate = TRUE, conf.int = TRUE) |>
filter(term != "(Intercept)") |>
mutate(significativo = p.value < 0.05)
ggplot(or_datos, aes(x = estimate, y = reorder(term, estimate))) +
geom_vline(xintercept = 1, linetype = "dashed", color = "gray50") +
geom_point(aes(color = significativo), size = 3) +
geom_errorbarh(aes(xmin = conf.low, xmax = conf.high,
color = significativo), height = 0.2) +
scale_color_manual(values = c("TRUE" = "#B85042", "FALSE" = "gray60")) +
labs(x = "Odds Ratio", y = NULL,
title = "Factores de riesgo de rotación") +
theme_minimal()
glance(modelo)
# # A tibble: 1 × 8
# null.deviance df.null logLik AIC BIC deviance df.residual nobs
# 1423. 1199 -652. 1312. 1332. 1304. 1196 1200
| Columna | Significado | Uso práctico |
|---|---|---|
null.deviance | Deviance del modelo sin predictores | Referencia: cuánto "error" hay sin explicar nada |
df.null | GL del modelo nulo | n − 1 |
logLik | Log-verosimilitud | Base para AIC, BIC; más alto = mejor ajuste |
AIC | Akaike Information Criterion | Comparar modelos: menor = mejor |
BIC | Bayesian Information Criterion | Similar al AIC pero penaliza más la complejidad |
deviance | Deviance del modelo ajustado | Menor que null.deviance si los predictores ayudan |
df.residual | GL residuales | n − k − 1 |
nobs | Número de observaciones | Verificación |
# Crear tabla comparativa de varios modelos
bind_rows(
glance(mod_nulo) |> mutate(modelo = "Nulo"),
glance(mod_1) |> mutate(modelo = "Satisfacción"),
glance(mod_3) |> mutate(modelo = "Sat + Antig + Edad"),
glance(mod_ext) |> mutate(modelo = "Extendido")
) |>
select(modelo, AIC, BIC, deviance, df.residual) |>
arrange(AIC)
augment(modelo, type.predict = "response")
# Devuelve el data frame original + columnas nuevas:
# .fitted = probabilidad predicha (con type.predict = "response")
# .resid = residuos del modelo
# .hat = leverage (influencia de cada observación)
# .cooksd = distancia de Cook (observaciones influyentes)
# .std.resid = residuos estandarizados
# Agregar probabilidades predichas al dataset original
innovaco_con_pred <- augment(modelo, newdata = innovaco,
type.predict = "response")
# Ahora puedes usar .fitted como probabilidad de rotación
innovaco_con_pred |>
select(id_empleado, nombre, departamento, rotacion, .fitted) |>
arrange(desc(.fitted)) |>
head(20)
# Identificar observaciones influyentes
diagnosticos <- augment(modelo)
# Puntos con alta distancia de Cook (influyentes)
diagnosticos |>
filter(.cooksd > 4 / nrow(innovaco)) |>
arrange(desc(.cooksd))
# Gráfico de residuos vs. fitted
ggplot(diagnosticos, aes(x = .fitted, y = .resid)) +
geom_point(alpha = 0.3) +
geom_hline(yintercept = 0, linetype = "dashed") +
labs(title = "Residuos vs. Valores ajustados")
broom no es solo para glm(). Funciona con la mayoría de los modelos estadísticos en R:
# Con prueba t
tidy(t.test(satisfaccion_laboral ~ rotacion, data = innovaco))
# Con chi-cuadrado
tidy(chisq.test(table(innovaco$departamento, innovaco$rotacion)))
# Con correlación
tidy(cor.test(innovaco$satisfaccion_laboral, innovaco$edad))
# Con regresión lineal
tidy(lm(ingreso_mensual ~ antiguedad_anios + educacion, data = innovaco))
# Con ANOVA
tidy(aov(satisfaccion_laboral ~ departamento, data = innovaco))
tidy(). Obtendrás un tibble limpio que puedes usar inmediatamente con dplyr y ggplot2, sin tener que extraer componentes manualmente con $.
| Función | Input | Output | Uso típico |
|---|---|---|---|
tidy(modelo) | Cualquier modelo | Tibble: 1 fila por término | Tabla de coeficientes, forest plot |
tidy(modelo, exponentiate = TRUE) | glm binomial | Tibble con odds ratios | Odds ratios para el VP |
tidy(modelo, conf.int = TRUE) | Cualquier modelo | Tibble con IC 95% | Forest plots con barras de error |
glance(modelo) | Cualquier modelo | Tibble: 1 fila total | Comparar AIC entre modelos |
augment(modelo) | Cualquier modelo | Datos + predicciones | Diagnósticos, residuos, leverage |
augment(modelo, type.predict = "response") | glm binomial | Datos + probabilidades | Ranking de riesgo de rotación |