Enlace de acceso al HTML publicado: Clic Aquí
A partir de la retroalimentación de la Actividad 1, no se requirieron modificaciones metodológicas estructurales en la delimitación clínica (CIE-10: H25). Se mantuvo la depuración de valores anómalos de estancia (menores a 0) y edades incompatibles, garantizando la consistencia del espacio muestral \(\Omega\).
ruta_base <- "GRD_PUBLICO_2024.txt"
set.seed(2026) # Semilla fija para reproducibilidad exigida
if (file.exists(ruta_base)) {
grd_base <- fread(ruta_base, sep = "|", encoding = "UTF-8")
} else {
# No existe base de datos...
}
# Construcción de Omega (Egresos hospitalarios válidos sin CMA)
omega <- grd_base %>%
filter(!grepl("CMA|AMBULATORI", TIPO_ACTIVIDAD, ignore.case = TRUE)) %>%
mutate(
fecha_ing = as.Date(FECHA_INGRESO),
f_alta = as.Date(FECHAALTA),
estancia = as.numeric(f_alta - fecha_ing),
edad = floor(as.numeric(fecha_ing - as.Date(FECHA_NACIMIENTO)) / 365.25)
) %>%
filter(!is.na(estancia) & estancia >= 0 & !is.na(edad) & edad >= 0 & edad <= 110)
N_omega <- nrow(omega)
# Definición de Eventos
cols_diag <- grep("^DIAGNOSTICO", names(omega), value = TRUE)
omega <- omega %>%
mutate(
E_p = grepl("^H25", trimws(DIAGNOSTICO1), ignore.case = TRUE),
E = if_any(all_of(cols_diag), ~ grepl("^H25", trimws(.x), ignore.case = TRUE)),
E_s = E & !E_p,
F_evt = grepl("FALLE|MUERTE|3", TIPOALTA, ignore.case = TRUE),
U = grepl("URGENCIA|1", TIPO_INGRESO, ignore.case = TRUE),
L = estancia > quantile(estancia, 0.75, na.rm = TRUE),
S_k = case_when(
IR_29301_SEVERIDAD %in% c("1", "2", "3") ~ as.character(IR_29301_SEVERIDAD),
TRUE ~ "Sin Registro"
),
G_j = cut(edad, breaks = c(-1, 49, 64, 79, Inf), labels = c("<50", "50-64", "65-79", "≥80"))
)
n_E <- sum(omega$E)
corte_estancia_larga <- quantile(omega$estancia, 0.75, na.rm = TRUE)El tamaño poblacional del espacio muestral es de \(N = 873.719\) episodios hospitalarios. La cohorte de estudio asociada a la Catarata Senil (\(E\)) está conformada por 389 episodios.
El evento de estancia larga (\(L\)) se configuró utilizando el percentil 75 de \(\Omega\), correspondiente a internaciones que superan los 7 días.
# Cálculo de probabilidades marginales
eventos_resumen <- data.frame(
Evento = c("E", "Ep", "Es", "F", "U", "L"),
Definición = c("Episodio registra Catarata Senil (H25)", "H25 como Diag. Principal", "H25 como Diag. Secundario", "Termina en Fallecimiento", "Ingresa por Urgencia", paste("Estancia Larga (> P75:", corte_estancia_larga, "días)")),
Conteos = c(sum(omega$E), sum(omega$E_p), sum(omega$E_s), sum(omega$F_evt), sum(omega$U), sum(omega$L))
) %>%
mutate(Probabilidad = Conteos / N_omega)
kable(eventos_resumen, digits = 4, caption = "Tabla 1: Eventos basales en el espacio muestral") %>% kable_styling(bootstrap_options = "striped")| Evento | Definición | Conteos | Probabilidad |
|---|---|---|---|
| E | Episodio registra Catarata Senil (H25) | 389 | 0.0004 |
| Ep | H25 como Diag. Principal | 108 | 0.0001 |
| Es | H25 como Diag. Secundario | 281 | 0.0003 |
| F | Termina en Fallecimiento | 26660 | 0.0305 |
| U | Ingresa por Urgencia | 545614 | 0.6245 |
| L | Estancia Larga (> P75: 7 días) | 212172 | 0.2428 |
Para garantizar la solidez axiomática, se verifican las reglas de la probabilidad en código:
# Complemento
P_F <- sum(omega$F_evt) / N_omega
P_no_F_formula <- 1 - P_F
P_no_F_conteo <- sum(!omega$F_evt) / N_omega
# Unión (E U F)
P_E <- sum(omega$E) / N_omega
P_E_inter_F <- sum(omega$E & omega$F_evt) / N_omega
P_E_union_F_formula <- P_E + P_F - P_E_inter_F
P_E_union_F_conteo <- sum((omega$E + omega$F_evt) > 0) / N_omega
verificacion_uniones <- data.frame(
Operación = c("Complemento de F (Supervivencia)", "Unión E U F (Catarata o Fallecimiento)"),
`Cálculo por Fórmula` = c(P_no_F_formula, P_E_union_F_formula),
`Cálculo por Conteo Directo` = c(P_no_F_conteo, P_E_union_F_conteo)
)
kable(verificacion_uniones, digits = 5, caption = "Tabla 2: Verificación axiomática") %>% kable_styling(bootstrap_options = "striped")| Operación | Cálculo.por.Fórmula | Cálculo.por.Conteo.Directo |
|---|---|---|
| Complemento de F (Supervivencia) | 0.96949 | 0.96949 |
| Unión E U F (Catarata o Fallecimiento) | 0.03094 | 0.03094 |
# Tabla de Contingencia E vs F
tabla_cont_EF <- addmargins(table(Catarata = omega$E, Fallecimiento = omega$F_evt))
rownames(tabla_cont_EF) <- c("No H25", "Sí H25", "Total")
colnames(tabla_cont_EF) <- c("Vivo", "Fallecido", "Total")
kable(tabla_cont_EF, caption = "Tabla 3: Contingencia Episodios H25 vs. Fallecimientos") %>% kable_styling(bootstrap_options = "striped")| Vivo | Fallecido | Total | |
|---|---|---|---|
| No H25 | 846686 | 26644 | 873330 |
| Sí H25 | 373 | 16 | 389 |
| Total | 847059 | 26660 | 873719 |
# Probabilidades
P_F_dado_E <- sum(omega$F_evt & omega$E) / sum(omega$E)
P_F_dado_noE <- sum(omega$F_evt & !omega$E) / sum(!omega$E)
P_F_dado_Ep <- sum(omega$F_evt & omega$E_p) / sum(omega$E_p)
# Evitar división por cero si no hay casos
P_F_dado_Es <- ifelse(sum(omega$E_s) > 0, sum(omega$F_evt & omega$E_s) / sum(omega$E_s), 0)Al calcular \(P(F\vert{}E)\) se obtiene un 4.11%, frente a un \(P(F\vert{}\overline{E})\) de 3.05%. Si se segrega la cohorte: \(P(F\vert{}E_p) =\) 0% y \(P(F\vert{}E_s) =\) 5.69%.
Los eventos no son independientes. La probabilidad de fallecer difiere considerablemente si la persona tiene catarata senil registrada (\(P(F|E) = 4.11\%\)) versus la probabilidad basal de fallecer en el hospital (\(P(F) = 3.05\%\)).
tabla_edad <- omega %>%
group_by(G_j) %>%
summarise(
Total_Grupo = n(),
Casos_H25 = sum(E),
`P(E|G_j)` = Casos_H25 / Total_Grupo
)
kable(tabla_edad, digits = 4, caption = "Tabla 4: Probabilidad de presentar H25 dado el grupo etario") %>% kable_styling(bootstrap_options = "striped")| G_j | Total_Grupo | Casos_H25 | P(E|G_j) |
|---|---|---|---|
| <50 | 479492 | 18 | 0.0000 |
| 50-64 | 151540 | 80 | 0.0005 |
| 65-79 | 169194 | 174 | 0.0010 |
| ≥80 | 73493 | 117 | 0.0016 |
ggplot(tabla_edad, aes(x = G_j, y = `P(E|G_j)`)) +
geom_col(fill = "#2c3e50") +
labs(title = "Probabilidad de presentar Catarata Senil según Grupo Etario", x = "Grupo Etario", y = "P(E | Gj)") +
scale_y_continuous(labels = scales::percent) + theme_minimal()Evaluamos la prolongación de la estadía \(P(L \vert{} E \cap U)\) frente a admisiones programadas \(P(L \vert{} E \cap \overline{U})\):
P_L_dado_EU <- sum(omega$L & omega$E & omega$U) / sum(omega$E & omega$U)
P_L_dado_E_noU <- sum(omega$L & omega$E & !omega$U) / sum(omega$E & !omega$U)
# Independencia L y U dentro de E
P_L_inter_U_dado_E <- sum(omega$L & omega$E & omega$U) / sum(omega$E)
P_L_dado_E <- sum(omega$L & omega$E) / sum(omega$E)
P_U_dado_E <- sum(omega$U & omega$E) / sum(omega$E)
Indep_prod <- P_L_dado_E * P_U_dado_EPara un paciente con H25 que ingresa por urgencia, la probabilidad de tener una estancia larga es \(P(L|E \cap U) = 47.53\%\). En contraste, si el ingreso es programado, cae a \(P(L|E \cap \overline{U}) = 9.04\%\). Al comprobar dependencia conjunta entre (\(L\)) y (\(U\)) dentro de la cohorte \(E\):\(P(L \cap U | E) = 0.2725\), mientras que el producto \(P(L|E) \cdot P(U|E) = 0.1783\). La desigualdad matemática ratifica la dependencia descriptiva entre ingresar por urgencia y tener una estancia extensa.
Descomponemos el fallecimiento \(P(F\vert{}E)\) utilizando la severidad del paciente como sistema de partición exhaustivo. Los episodios sin nivel registrado se catalogaron como “Sin Registro” para cubrir el 100% de la cohorte \(E\).
# Partición sobre la cohorte E
cohorte_E <- omega %>% filter(E == TRUE)
tabla_total <- cohorte_E %>%
group_by(S_k) %>%
summarise(
`P(Sk | E)` = n() / nrow(cohorte_E),
`P(F | E inter Sk)` = sum(F_evt) / n(),
Producto = (n() / nrow(cohorte_E)) * (sum(F_evt) / n())
)
kable(tabla_total, digits = 5, caption = "Tabla 5: Ley de probabilidad total para el fallecimiento según Severidad") %>% kable_styling(bootstrap_options = "striped")| S_k | P(Sk | E) | P(F | E inter Sk) | Producto |
|---|---|---|---|
| 1 | 0.32905 | 0.00000 | 0.00000 |
| 2 | 0.39846 | 0.01290 | 0.00514 |
| 3 | 0.27249 | 0.13208 | 0.03599 |
La suma de los productos es 0.04113. Al calcular \(P(F\vert{}E)\) por conteo directo se obtiene 0.04113. La diferencia es cero. El nivel de severidad que aporta más fallecimientos brutos al total suele ser distinto del nivel con la mayor probabilidad intrínseca de fallecimiento (\(P(F \vert{} E \cap S_k)\)), demostrando que la severidad extrema concentra altísima mortalidad, pero los niveles moderados pueden aportar mayor volumen de casos.
Aplicamos Bayes para invertir el condicionamiento de probabilidades y lo verificamos con el método frecuentista sobre \(\Omega\).
# Caso 1: Invertir Condicional P(E|F)
P_E_dado_F_bayes <- (P_F_dado_E * P_E) / P_F
P_E_dado_F_conteo <- sum(omega$E & omega$F_evt) / sum(omega$F_evt)
# Caso 2: Severidad a posteriori P(Sk | F inter E)
tabla_bayes_sev <- cohorte_E %>%
group_by(S_k) %>%
summarise(
`Priori P(Sk|E)` = n() / nrow(cohorte_E),
`Likelihood P(F|E,Sk)` = sum(F_evt) / n()
) %>%
mutate(
Marginal_F_E = sum(`Priori P(Sk|E)` * `Likelihood P(F|E,Sk)`),
`Posteriori P(Sk|F,E)` = (`Likelihood P(F|E,Sk)` * `Priori P(Sk|E)`) / Marginal_F_E
)
# Caso 3: Rol diagnóstico dada estancia larga P(Ep | L inter E)
P_L_dado_Ep <- sum(omega$L & omega$E_p) / sum(omega$E_p)
P_Ep_dado_E <- sum(omega$E_p) / sum(omega$E)
P_L_dado_E_global <- sum(omega$L & omega$E) / sum(omega$E)
P_Ep_dado_L_E_bayes <- (P_L_dado_Ep * P_Ep_dado_E) / P_L_dado_E_global
P_Ep_dado_L_E_conteo <- sum(omega$E_p & omega$L) / sum(omega$E & omega$L)La evidencia de la muerte (\(F\)) actualiza las probabilidades de pertenecer a una severidad.
kable(tabla_bayes_sev %>% select(S_k, `Priori P(Sk|E)`, `Posteriori P(Sk|F,E)`), digits = 4, caption = "Tabla 6: Severidad A Priori vs A Posteriori") %>% kable_styling()| S_k | Priori P(Sk|E) | Posteriori P(Sk|F,E) |
|---|---|---|
| 1 | 0.3290 | 0.000 |
| 2 | 0.3985 | 0.125 |
| 3 | 0.2725 | 0.875 |
tabla_bayes_sev_long <- tabla_bayes_sev %>%
select(S_k, `Priori P(Sk|E)`, `Posteriori P(Sk|F,E)`) %>%
pivot_longer(cols = 2:3, names_to = "Momento", values_to = "Probabilidad")
ggplot(tabla_bayes_sev_long, aes(x = S_k, y = Probabilidad, fill = Momento)) +
geom_col(position = "dodge") + theme_minimal() + labs(title = "Cambio Bayesiano de Probabilidad en Severidad", x = "Nivel de Severidad")Dado que la pauta prohíbe el uso de marcadores diagnósticos directos (circularidad), se define operacionalmente el marcador \(M\) como “Paciente mayor o igual a 65 años que ingresa en modalidad programada (No Urgencia)”. Este marcador es estrictamente administrativo y logístico.
omega <- omega %>%
mutate(M = (edad >= 65 & U == FALSE))
tabla_M_E <- addmargins(table(Marcador_M = omega$M, Catarata_E = omega$E))
kable(tabla_M_E, caption = "Tabla 7: Contingencia Marcador M vs Enfermedad E en Omega") %>% kable_styling()| FALSE | TRUE | Sum | |
|---|---|---|---|
| FALSE | 816137 | 279 | 816416 |
| TRUE | 57193 | 110 | 57303 |
| Sum | 873330 | 389 | 873719 |
P_M_dado_E <- sum(omega$M & omega$E) / sum(omega$E) # Sensibilidad
P_noM_dado_noE <- sum(!omega$M & !omega$E) / sum(!omega$E) # Especificidad
P_M <- sum(omega$M) / N_omega
VPP_bayes <- (P_M_dado_E * P_E) / P_M
VPN_bayes <- (P_noM_dado_noE * (1 - P_E)) / (1 - P_M)
VPP_conteo <- sum(omega$E & omega$M) / sum(omega$M)# Simulación de curva VPP variando P(E) con Sens y Esp fijas
p_e_vec <- seq(0.001, 0.15, length.out = 100)
vpp_vec <- (P_M_dado_E * p_e_vec) / ((P_M_dado_E * p_e_vec) + ((1 - P_noM_dado_noE) * (1 - p_e_vec)))
df_vpp <- data.frame(P_E = p_e_vec, VPP = vpp_vec)
ggplot(df_vpp, aes(x = P_E, y = VPP)) +
geom_line(color = "darkred", size = 1) +
geom_vline(xintercept = P_E, linetype = "dashed") +
annotate("text", x = P_E + 0.01, y = max(vpp_vec)*0.8, label = "Prevalencia en BD") +
theme_minimal() + labs(title = "Efecto de la prevalencia P(E) sobre el Valor Predictivo Positivo (VPP)", x = "Proporción de E en la Base (A priori)", y = "VPP P(E|M)")Se ejecuta el Teorema de Bayes sobre muestras extraídas aleatoriamente de \(\Omega\) (método Monte Carlo), evaluando la estabilidad de la estimación probabilística \(P(E\vert{}F)\) a medida que se reduce la incertidumbre muestral (\(n\)).
set.seed(2026)
B <- 1000
tamanos_n <- c(100, 500, 1000, 5000, 20000)
resultados_sim <- data.frame()
for (n in tamanos_n) {
estimaciones <- numeric(B)
for (i in 1:B) {
# Evitar problemas si N_omega es más pequeño que n en la simulación sintética
n_sample <- min(n, N_omega)
idx <- sample(1:N_omega, n_sample, replace = FALSE)
muestra <- omega[idx, ]
n_F <- sum(muestra$F_evt)
if (n_F == 0) {
estimaciones[i] <- NA
} else {
estimaciones[i] <- sum(muestra$E & muestra$F_evt) / n_F
}
}
df_temp <- data.frame(n = as.factor(n), Est = estimaciones)
resultados_sim <- rbind(resultados_sim, df_temp)
}
resumen_sim <- resultados_sim %>%
group_by(n) %>%
summarise(
Mediana_Est = median(Est, na.rm = TRUE),
RIC_Est = IQR(Est, na.rm = TRUE),
Pct_NA = sum(is.na(Est)) / B * 100
)
kable(resumen_sim, digits = 4, caption = "Tabla 8: Resumen estadístico de simulaciones MCMC") %>% kable_styling()| n | Mediana_Est | RIC_Est | Pct_NA |
|---|---|---|---|
| 100 | 0 | 0.0000 | 5.3 |
| 500 | 0 | 0.0000 | 0.0 |
| 1000 | 0 | 0.0000 | 0.0 |
| 5000 | 0 | 0.0000 | 0.0 |
| 20000 | 0 | 0.0016 | 0.0 |
ggplot(resultados_sim %>% filter(!is.na(Est)), aes(x = n, y = Est, fill = n)) +
geom_boxplot(alpha = 0.6) +
geom_hline(yintercept = P_E_dado_F_conteo, linetype = "dashed", color = "red", size = 1) +
theme_minimal() + labs(title = "Distribución de P(E|F) estimada por Tamaño de Muestra (n)", y = "Probabilidad Estimada", subtitle = "La línea roja indica el valor poblacional en Omega")A medida que \(n\) aumenta (Ley de los Grandes Números), la dispersión (Rango Intercuartílico) se comprime hacia la línea roja del valor real de \(\Omega\). En muestras de \(n=100\), el alto porcentaje de valores NA (cero fallecidos detectados) evidencia la imposibilidad técnica para la jefatura de tomar decisiones probabilísticas seguras evaluando bases pequeñas en enfermedades infrecuentes.
Limitaciones del Análisis: * Las probabilidades condicionales obtenidas son estrictamente descriptivas de la cohorte analizada, no extrapolables como métricas de riesgo individual o causalidad epidemiológica poblacional (por ejemplo, una alta \(P(F|E)\) no indica bajo ningún aspecto que la catarata sea la causa biológica de la muerte). * La naturaleza logitudinal de eventos por paciente se pierde en la unidad “episodio”; el condicionamiento no reconoce si es un segundo ingreso del mismo RUT. * La calidad de los axiomas de partición descansa exclusivamente sobre la exactitud de codificación de la plataforma hospitalaria.
Respuesta Directa a Jefatura (Marcador M): El marcador administrativo sugerido (Adulto Mayor con ingreso Programado) no posee utilidad clínica para detectar casos aislados. Posee un Valor Predictivo Positivo (VPP) abismalmente bajo de \(P(E|M) = 0.19\%\). A pesar de poseer una correcta sensibilidad teórica, la baja prevalencia intrínseca de \(P(E)\) en la base genera una avalancha de “falsos positivos” procedentes de otras admisiones programadas geriátricas.
En el desarrollo de este informe se utilizó Gemini AI con el propósito de optimizar el código en R para el procesamiento eficiente de macrodatos, la parametrización de variables dinámicas y la maquetación estructural en RMarkdown.
Todo el código generado fue ejecutado y auditado localmente por el autor, verificando paso a paso que la lógica de filtrado y los cálculos estadísticos coincidieran estrictamente con el diccionario oficial del GRD 2024 de FONASA y que los conteos de la cohorte concordaran algebraicamente.
Base de datos principal: Base Pública de Grupos Relacionados por el Diagnóstico (GRD) 2024, Fondo Nacional de Salud (FONASA), Gobierno de Chile.
Fecha de extracción de los datos: 11 de Septiembre de 2026.