Preparación del ambiente de trabajo
library(ggplot2)
library(dplyr)
library(broom)
set.seed(2025)
Simulación y exploración de datos
n <- 200
x1 <- rnorm(n)
x2 <- sample(c("A", "B"), n, replace = TRUE)
prob <- 1 / (1 + exp(-(0.5 * x1 + ifelse(x2 == "B", 1, 0))))
y <- rbinom(n, 1, prob)
df <- data.frame(y = as.factor(y), x1 = x1, x2 = as.factor(x2))
ggplot(df, aes(x = x1, fill = y)) +
geom_density(alpha = 0.5) +
facet_wrap(~x2) +
labs(title = "Distribución de x1 por clase y y categoría x2")

Ajuste del modelo de regresión logística
modelo_logit <- glm(y ~ x1 + x2, data = df, family = "binomial")
summary(modelo_logit)
##
## Call:
## glm(formula = y ~ x1 + x2, family = "binomial", data = df)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.1209 0.2036 0.594 0.552669
## x1 0.6034 0.1649 3.659 0.000253 ***
## x2B 0.9121 0.3142 2.903 0.003695 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 265.63 on 199 degrees of freedom
## Residual deviance: 242.18 on 197 degrees of freedom
## AIC: 248.18
##
## Number of Fisher Scoring iterations: 4
Evaluación del modelo
df$prob_pred <- predict(modelo_logit, type = "response")
df$y_pred <- ifelse(df$prob_pred > 0.5, 1, 0)
table(Predicho = df$y_pred, Real = df$y)
## Real
## Predicho 0 1
## 0 29 21
## 1 47 103
ggplot(df, aes(x = prob_pred, fill = y)) +
geom_histogram(bins = 30, position = "identity", alpha = 0.6) +
labs(title = "Distribución de probabilidades predichas")

Interpretación de coeficientes
broom::tidy(modelo_logit, exponentiate = TRUE, conf.int = TRUE)
## # A tibble: 3 × 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 1.13 0.204 0.594 0.553 0.758 1.69
## 2 x1 1.83 0.165 3.66 0.000253 1.33 2.55
## 3 x2B 2.49 0.314 2.90 0.00369 1.36 4.66
LS0tDQphdXRob3I6IEd1c3Rhdm8gTWFydMOtbmV6IFZhbGRlcw0KZGF0ZTogJ2ByIGZvcm1hdChTeXMuRGF0ZSgpKWAnDQp0aXRsZTogUmVncmVzacOzbiBjb24gZWZlY3RvcyBmaWpvcw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNS4wDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KDQojIyMgUHJlcGFyYWNpw7NuIGRlbCBhbWJpZW50ZSBkZSB0cmFiYWpvDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShicm9vbSkNCnNldC5zZWVkKDIwMjUpDQpgYGANCg0KLS0tDQoNCiMjIyBTaW11bGFjacOzbiB5IGV4cGxvcmFjacOzbiBkZSBkYXRvcw0KDQpgYGB7cn0NCm4gPC0gMjAwDQp4MSA8LSBybm9ybShuKQ0KeDIgPC0gc2FtcGxlKGMoIkEiLCAiQiIpLCBuLCByZXBsYWNlID0gVFJVRSkNCnByb2IgPC0gMSAvICgxICsgZXhwKC0oMC41ICogeDEgKyBpZmVsc2UoeDIgPT0gIkIiLCAxLCAwKSkpKQ0KeSA8LSByYmlub20obiwgMSwgcHJvYikNCg0KZGYgPC0gZGF0YS5mcmFtZSh5ID0gYXMuZmFjdG9yKHkpLCB4MSA9IHgxLCB4MiA9IGFzLmZhY3Rvcih4MikpDQoNCmdncGxvdChkZiwgYWVzKHggPSB4MSwgZmlsbCA9IHkpKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKw0KICBmYWNldF93cmFwKH54MikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1Y2nDs24gZGUgeDEgcG9yIGNsYXNlIHkgeSBjYXRlZ29yw61hIHgyIikNCmBgYA0KDQotLS0NCg0KIyMjIEFqdXN0ZSBkZWwgbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbG9nw61zdGljYQ0KDQpgYGB7cn0NCm1vZGVsb19sb2dpdCA8LSBnbG0oeSB+IHgxICsgeDIsIGRhdGEgPSBkZiwgZmFtaWx5ID0gImJpbm9taWFsIikNCnN1bW1hcnkobW9kZWxvX2xvZ2l0KQ0KYGBgDQoNCi0tLQ0KDQojIyMgRXZhbHVhY2nDs24gZGVsIG1vZGVsbw0KDQpgYGB7cn0NCmRmJHByb2JfcHJlZCA8LSBwcmVkaWN0KG1vZGVsb19sb2dpdCwgdHlwZSA9ICJyZXNwb25zZSIpDQpkZiR5X3ByZWQgPC0gaWZlbHNlKGRmJHByb2JfcHJlZCA+IDAuNSwgMSwgMCkNCg0KdGFibGUoUHJlZGljaG8gPSBkZiR5X3ByZWQsIFJlYWwgPSBkZiR5KQ0KDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gcHJvYl9wcmVkLCBmaWxsID0geSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIsIGFscGhhID0gMC42KSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnVjacOzbiBkZSBwcm9iYWJpbGlkYWRlcyBwcmVkaWNoYXMiKQ0KYGBgDQoNCi0tLQ0KDQojIyMgSW50ZXJwcmV0YWNpw7NuIGRlIGNvZWZpY2llbnRlcw0KDQpgYGB7cn0NCmJyb29tOjp0aWR5KG1vZGVsb19sb2dpdCwgZXhwb25lbnRpYXRlID0gVFJVRSwgY29uZi5pbnQgPSBUUlVFKQ0KYGBgDQo=