# Manual calibration plot using deciles of predicted probability
cal_df <- data.frame(
pred = pred_glm,
obs = as.numeric(test$SWP)
)
# Cut into 10 equal-width bins
cal_df$bin <- cut(cal_df$pred, breaks = seq(0, 1, by = 0.1),
include.lowest = TRUE)
cal_summary <- cal_df |>
group_by(bin) |>
summarise(
mean_pred = mean(pred),
obs_rate = mean(obs),
n = n(),
.groups = "drop"
)
ggplot(cal_summary, aes(mean_pred, obs_rate)) +
geom_abline(slope = 1, intercept = 0, linetype = "dashed", colour = "grey50") +
geom_line(colour = "#3498db", linewidth = 1) +
geom_point(aes(size = n), colour = "#2c3e50") +
scale_size_continuous(range = c(2, 8), name = "n in bin") +
scale_x_continuous(limits = c(0, 1), labels = scales::percent_format()) +
scale_y_continuous(limits = c(0, 1), labels = scales::percent_format()) +
labs(title = "Calibration plot — Logistic regression on SWP data",
subtitle = "Dashed line = perfect calibration",
x = "Mean predicted probability", y = "Observed event rate") +
theme_minimal()
