A continuación un análisis de diferentes bases de datos:
base_datos<-read_excel("/Users/SCR/Desktop/ANALÍTICA_DE_DATOS/PROMPT_2/Medical Appointment Scheduling System.xlsx")En la administración de recursos sanitarios, entender el comportamiento de las citas y la demografía de los pacientes es crucial para optimizar la capacidad operativa. Primero, realizamos la simulación importando los datos del Appointments Dataset.
datos_citas <- read_excel ("/Users/SCR/Desktop/ANALÍTICA_DE_DATOS/PROMPT_2/Medical Appointment Scheduling System.xlsx")## 1. Construcción del Espacio Muestral y Eventos con `sample()`
En teoría de la probabilidad, el **Espacio Muestral (\(\Omega\))** es el conjunto de todos los resultados posibles de un experimento aleatorio. Un **Evento** es cualquier subconjunto de ese espacio muestral.
Para un administrador sanitario, realizar una auditoría aleatoria de historias clínicas o citas es un procedimiento estándar para evaluar la calidad del servicio.
### A. Simulación de una muestra aleatoria (Auditoría de Citas)
Imaginemos que seleccionamos al azar un grupo de 100 citas para verificar si los pacientes asistieron o no (`status`). Utilizaremos la función `sample()` para extraer los índices de las filas.
``` r
# Fijamos una semilla para que los resultados sean reproducibles
set.seed(123)
# Definimos el tamaño de la muestra
tamano_muestra <- 100
# Definimos el espacio muestral: todos los índices de citas disponibles (1 a 111,488)
espacio_muestral_id <- datos_citas$appointment_id
# Extraemos la muestra aleatoria sin reemplazo
indices_seleccionados <- sample(espacio_muestral_id, size = tamano_muestra, replace = FALSE)
# Filtramos nuestra base de datos para obtener las citas seleccionadas
auditoria_citas <- datos_citas %>% filter(appointment_id %in% indices_seleccionados)
# Visualizamos las primeras 6 citas de la auditoría
head(auditoria_citas)
A partir de nuestra muestra de auditoría, calculamos la frecuencia de
ocurrencia de dos eventos de alto interés administrativo: *
Evento A: El paciente asistió a la cita
(status == "Showed up"). * Evento B: El
paciente es de sexo femenino (sex == "F").
# Contabilizar la ocurrencia de los eventos en la muestra
frecuencia_asistencia <- sum(auditoria_citas$status == "Showed up")
frecuencia_mujeres <- sum(auditoria_citas$sex == "F")
# Calcular las probabilidades empíricas (frecuencias relativas)
prob_empirica_A <- frecuencia_asistencia / tamano_muestra # P(A)
prob_empirica_B <- frecuencia_mujeres / tamano_muestra # P(B)Con base en la simulación realizada mediante la función
sample(), podemos extraer las siguientes conclusiones desde
la perspectiva de la gestión sanitaria:
replace = FALSE, garantizamos que una misma cita no sea
auditada dos veces, emulando un control de calidad real en un entorno
hospitalario. El espacio muestral finito consta de las 111,488 citas
registradas.Vamos a analizar simultáneamente dos variables críticas de toda la
base de datos (datos_citas): el ausentismo
(status) y el grupo de edad (age_group). Esto
nos permitirá evaluar si la edad influye en que un paciente falte a su
cita.
# Generamos la tabla de contingencia de frecuencias absolutas (conteos de pacientes)
tabla_conteos <- table(datos_citas$status, datos_citas$age_group)
# Mostramos la tabla en el reporte
tabla_conteos##
## 0-18 19-40 41-65 65+
## No Show 4410 6724 6786 4408
## Showed up 17878 26869 26813 17600
Para convertir estos conteos en probabilidades, dividimos cada celda
por el gran total de la población de la base de datos. En R, esto se
automatiza con la función prop.table().
# Calculamos las probabilidades conjuntas y marginales
tabla_probabilidades <- prop.table(tabla_conteos)
# Mostramos la tabla con las probabilidades redondeadas a 4 decimales para mayor claridad
round(tabla_probabilidades, 4)##
## 0-18 19-40 41-65 65+
## No Show 0.0396 0.0603 0.0609 0.0395
## Showed up 0.1604 0.2410 0.2405 0.1579
A partir de las tablas de contingencia generadas sobre el total de las 111,488 citas, el administrador de salud puede extraer las siguientes conclusiones estadísticas y operativas:
table() nos proporciona el número exacto de
pacientes en cada combinación (por ejemplo, cuántos adultos mayores no
asistieron), prop.table() transforma estos datos en un
formato probabilístico (valores entre 0 y 1).runif(),
rbinom() y dpois()En la administración de recursos sanitarios, los flujos de pacientes y los tiempos de atención son variables e inciertos. Las distribuciones de probabilidad nos permiten modelar esta incertidumbre para prever escenarios, dimensionar el personal necesario y evitar el colapso de los servicios.
runif()) para
Tiempos de EsperaImagina que la dirección del hospital implementó una nueva sala de triaje rápido. Los estudios preliminares sugieren que el tiempo que un paciente pasa en esta sala desde que ingresa hasta que es atendido varía de forma equiprobable entre un mínimo de 5 minutos y un máximo de 25 minutos.
Simularemos los tiempos de espera de las próximas 1,000 citas para evaluar el comportamiento del servicio.
set.seed(456)
n_simulaciones <- 1000
# Generamos una muestra continua de tiempos de espera entre 5 y 25 minutos
tiempos_espera_sim <- runif(n = n_simulaciones, min = 5, max = 25)
# Calculamos métricas descriptivas clave para la gestión
media_espera <- mean(tiempos_espera_sim)
max_espera <- max(tiempos_espera_sim)rbinom()) para el Control de
Ausentismo (“No Show”)Supongamos que los datos históricos de tu hospital reflejan una tasa de ausentismo constante del 20% (\(p = 0.20\)). Si un médico tiene agendados a 20 pacientes en su turno matutino (\(n = 20\)), queremos simular cuántos pacientes faltarán en 500 días de consulta diferentes para entender el riesgo operativo.
set.seed(789)
# Simulación de 500 días de consulta con 20 pacientes agendados por día
inasistencias_diarias <- rbinom(n = 500, size = 20, prob = 0.20)
# Contamos cuántas veces ocurrieron escenarios específicos (ej. que falten más de 5 pacientes)
dias_alta_inasistencia <- sum(inasistencias_diarias > 5)
porcentaje_critico <- (dias_alta_inasistencia / 500) * 100dpois()) para la Llegada de
Urgencias por HoraSupongamos que el servicio de urgencias del hospital recibe, en promedio, a 4 pacientes por hora (\(\lambda = 4\)). Como administradores, necesitamos calcular con precisión matemática la probabilidad exacta de recibir un número específico de pacientes en la próxima hora para optimizar el número de médicos de guardia.
# Parámetro Lambda (promedio de llegadas)
lambda_urgencias <- 4
# Calculamos la probabilidad exacta de recibir 0, 2, 4 y 7 pacientes
prob_0 <- dpois(x = 0, lambda = lambda_urgencias)
prob_2 <- dpois(x = 2, lambda = lambda_urgencias)
prob_4 <- dpois(x = 4, lambda = lambda_urgencias) # Justo el promedio
prob_7 <- dpois(x = 7, lambda = lambda_urgencias) # Escenario de alta demandaLas simulaciones probabilísticas aportan un valor estratégico incalculable para el modelado de la capacidad instalada:
runif):
La simulación arrojó un tiempo promedio de espera de 15.38
minutos. Al tratarse de una distribución uniforme, la
probabilidad de esperar 6 minutos es la misma que la de esperar 24
minutos. Para el gestor de recursos, saber que el tiempo máximo simulado
se acerca a los 25 minutos ayuda a establecer acuerdos
de nivel de servicio (SLA) y a gestionar las expectativas de los
usuarios en las salas de espera.rbinom): En la simulación de 500 días de trabajo,
hubo 100 días (un 20% del tiempo) en
los cuales faltaron más de 5 pacientes a la consulta del médico en un
solo turno. Un administrador sanitario puede usar estos escenarios
simulados para justificar una estrategia de sobreagendación
controlada (e.g., citar a 22 pacientes sabiendo
estadísticamente el riesgo de que falten varios) y así garantizar que
las horas del personal médico estén totalmente financiadas y
aprovechadas.dpois): Utilizando la función de densidad de
Poisson, determinamos los siguientes riesgos matemáticos para la
asignación de personal:
r-, d- y p-En la gestión sanitaria, muchas variables clave (como la edad de la
población, los costos de los tratamientos o los tiempos exactos de
cirugía) son continuas. Para analizarlas de forma
rigurosa, un administrador utiliza: * Funciones que empiezan con
r (rnorm, rexp,
runif): Generan datos aleatorios basados en la realidad del
servicio. * Funciones que empiezan con d
(dnorm, dexp): Calculan la altura de la curva
de densidad. * Funciones que empiezan con
p (pnorm, pexp):
Calculan la probabilidad acumulada (el área bajo la curva hasta un punto
específico), respondiendo a preguntas como “¿cuál es la probabilidad
de que ocurra un evento menor o igual a X?”.
Supongamos que los datos de facturación indican que la edad de los pacientes hospitalizados se distribuye de forma Normal, con una media de 55 años y una desviación estándar de 12 años.
Como gestores, simularemos una muestra de 1,000 pacientes y calcularemos probabilidades específicas para la planeación de camas de geriatría u obstetricia.
set.seed(101)
# 1. Simulación de datos de edad para 1,000 pacientes
edades_simuladas <- rnorm(n = 1000, mean = 55, sd = 12)
# 2. Cálculo de Probabilidad Acumulada con pnorm()
# ¿Cuál es la probabilidad de que un paciente ingresado al azar tenga 40 años o menos?
prob_menor_40 <- pnorm(q = 40, mean = 55, sd = 12)
# ¿Cuál es la probabilidad de que un paciente tenga más de 65 años (población de riesgo)?
# Usamos lower.tail = FALSE para calcular la probabilidad hacia la derecha de la curva (P > 65)
prob_mayor_65 <- pnorm(q = 65, mean = 55, sd = 12, lower.tail = FALSE)
# 3. Uso de la densidad con dnorm()
# Evaluamos la altura de la curva exactamente a los 55 años (la media)
densidad_en_media <- dnorm(x = 55, mean = 55, sd = 12)La Distribución Exponencial es el modelo estándar en la teoría de colas hospitalarias para medir el tiempo que transcurre entre eventos independientes o la duración de un servicio.
Imaginemos que el tiempo que un médico general tarda en atender a un paciente en consulta externa sigue una distribución exponencial con una tasa (\(\lambda\)) de 0.05 pacientes por minuto (lo que equivale a un tiempo promedio de atención de \(1 / 0.05 = 20\) minutos).
set.seed(202)
# 1. Simulación de los tiempos de atención de 1,000 consultas
tiempos_atencion_sim <- rexp(n = 1000, rate = 0.05)
# 2. Cálculo de Probabilidad Acumulada con pexp()
# ¿Cuál es la probabilidad de que una consulta se resuelva rápido, en 15 minutos o menos?
prob_atencion_rapida <- pexp(q = 15, rate = 0.05)
# ¿Cuál es la probabilidad de que una consulta se extienda más de 30 minutos?
prob_atencion_larga <- pexp(q = 30, rate = 0.05, lower.tail = FALSE)Volviendo a la distribución uniforme continua (vistas sus bases en el apartado anterior), consideremos que el tiempo de traslado de una ambulancia desde la base central hasta la zona periférica varía uniformemente entre un mínimo de 10 minutos y un máximo de 30 minutos.
set.seed(303)
# 1. Simulación de 1,000 tiempos de traslado continuos
traslados_sim <- runif(n = 1000, min = 10, max = 30)
# En una distribución uniforme continua, la probabilidad acumulada se puede calcular analíticamente,
# pero en R podemos usar la función punif() para calcular la probabilidad de tardar menos de 15 minutos.
prob_traslado_rapido <- punif(q = 15, min = 10, max = 30)El análisis analítico de las distribuciones continuas permite pasar de la recopilación de datos a la planeación estratégica de recursos:
rnorm /
pnorm):
pnorm() revela que existe una
probabilidad del 10.56% de que un paciente
hospitalizado elegido al azar sea menor o igual a 40 años.dnorm(55) nos da el valor de
0.0332, que representa el punto más alto de la campana
de Gauss (la densidad máxima de la población en la media).rexp /
pexp):
pexp()
indica que la probabilidad de que un médico termine una consulta en 15
minutos o menos es del 52.76%.runif /
punif):
punif() que la probabilidad de llegar al lugar del
incidente en 15 minutos o menos es del 25%. Si la norma
técnica exige tiempos de respuesta menores a 15 minutos para situaciones
críticas, un porcentaje de efectividad de apenas el 25% alertará al
administrador sobre la necesidad urgente de reubicar estratégicamente
ambulancias en subestaciones periféricas.En la gestión sanitaria, los datos crudos o las tablas extensas pueden resultar difíciles de digerir para una junta directiva o un comité epidemiológico. La visualización interactiva nos permite explorar la variabilidad, identificar patrones de comportamiento y comunicar los riesgos operativos de forma clara y contundente.
Para lograr esto, combinaremos la potencia estética de
ggplot2 con la interactividad de la librería
plotly mediante la función ggplotly().
Visualizaremos las 1,000 edades simuladas del personal hospitalario mediante un histograma interactivo, superponiendo la curva teórica de la campana de Gauss.
# Creamos un data frame con los datos de la simulación normal
df_normal <- data.frame(Edad = edades_simuladas)
# Construimos el gráfico base con ggplot2
g_normal <- ggplot(df_normal, aes(x = Edad)) +
geom_histogram(aes(y = ..density..), binwidth = 2, fill = "#2c3e50", color = "white", alpha = 0.8) +
stat_function(fun = dnorm, args = list(mean = 55, sd = 12), color = "#e74c3c", size = 1.2) +
labs(title = "Distribución de Edades de Pacientes Hospitalizados",
x = "Edad (Años)",
y = "Densidad") +
theme_minimal()
# Lo transformamos en interactivo
ggplotly(g_normal)Analizaremos cómo se distribuyen los tiempos de atención médica. Al ser un comportamiento exponencial, observaremos visualmente la alta concentración de consultas rápidas y la larga “cola” de consultas complejas.
# Creamos el data frame para la simulación exponencial
df_exponencial <- data.frame(Tiempo = tiempos_atencion_sim)
# Construimos el gráfico base
g_exponencial <- ggplot(df_exponencial, aes(x = Tiempo)) +
geom_histogram(aes(y = ..density..), binwidth = 3, fill = "#16a085", color = "white", alpha = 0.8) +
stat_function(fun = dexp, args = list(rate = 0.05), color = "#d35400", size = 1.2) +
labs(title = "Distribución de Tiempos de Atención en Consulta Externa",
x = "Duración de la Consulta (Minutos)",
y = "Densidad") +
theme_minimal()
# Lo transformamos en interactivo
ggplotly(g_exponencial)Para el administrador, es vital saber con qué frecuencia se repiten los escenarios de “No Show”. Graficaremos los 500 días de consulta simulados utilizando un gráfico de barras, destacando con un cambio de color el umbral crítico (más de 5 inasistencias por turno).
# Creamos el data frame y una variable lógica para identificar el riesgo crítico
df_binomial <- data.frame(Faltas = inasistencias_diarias) %>%
mutate(Riesgo = ifelse(Faltas > 5, "Crítico (>5 faltas)", "Normal (<=5 faltas)"))
# Construimos el gráfico de barras
g_binomial <- ggplot(df_binomial, aes(x = Faltas, fill = Riesgo)) +
geom_bar(color = "white", alpha = 0.9) +
scale_fill_manual(values = c("Normal (<=5 faltas)" = "#3498db", "Crítico (>5 faltas)" = "#e74c3c")) +
labs(title = "Frecuencia de Inasistencias Diarias Simuladas",
x = "Número de Pacientes Ausentes por Día",
y = "Cantidad de Días (Frecuencia)") +
theme_minimal() +
theme(legend.title = element_blank())
# Lo transformamos en interactivo
ggplotly(g_binomial)Al interactuar con los gráficos resultantes en el informe HTML final, el administrador de recursos sanitarios puede extraer conclusiones visuales inmediatas:
En la administración de recursos sanitarios, la Estadística Descriptiva es el punto de partida obligatorio para diagnosticar el estado de los servicios. Antes de proponer cambios operativos, un gestor debe responder con precisión preguntas básicas como: ¿Cuánto espera en promedio un paciente?, ¿Qué tan dispersos están los tiempos de consulta? o ¿Cuál es el comportamiento general de la agenda?
Para responder esto utilizando los datos reales del Appointments Dataset, aplicaremos las funciones estadísticas base de R.
### A. Cálculo de Métricas Individuales de Tendencia Central y Dispersión
Analizaremos de forma específica dos variables críticas para la satisfacción del usuario y la productividad médica:
1. **`waiting_time` (Tiempo de espera):** Minutos que espera el paciente antes de ser atendido.
2. **`appointment_duration` (Duración de la cita):** Tiempo en minutos que dura la atención médica.
``` r
# 1. Indicadores de Tendencia Centralmedia_espera <- mean(datos_citas$waiting_time, na.rm = TRUE)
mediana_espera <- median(datos_citas$waiting_time, na.rm = TRUE)
# 2. Indicadores de Dispersión o Variabilidad
desviacion_duracion <-sd(datos_citas$appointment_id, na.rm = TRUE)
varianza_duracion <-var(datos_citas$appointment_id, na.rm = TRUE)
# 3. Rangos (Valores Mínimo y Máximo)
rango_espera <- range(datos_citas$waiting_time, na.rm = TRUE)
### B. Resumen Ejecutivo Multivariable con `summary()`
En lugar de calcular cada métrica una por una, la función `summary()` nos ofrece una visión holística e inmediata de las variables numéricas y categóricas, mostrando cuartiles, valores atípicos (outliers) y totales.
# Seleccionamos un subconjunto de variables operativas y demográficas clave para el análisis
variables_interes <- datos_citas %>%
select(waiting_time, appointment_duration, age, status)
# Generamos el resumen estadístico automatizado
resumen_operativo <- summary(variables_interes)
# Mostramos el resumen en el reporte
resumen_operativo## waiting_time appointment_duration age status
## Min. : 0.00 Min. :-3 Min. :-36.00 Length :111488
## 1st Qu.: 6.00 1st Qu.:17 1st Qu.: 33.00 N.unique : 2
## Median : 14.00 Median :20 Median : 45.00 N.blank : 0
## Mean : 20.07 Mean :20 Mean : 44.91 Min.nchar: 7
## 3rd Qu.: 28.00 3rd Qu.:23 3rd Qu.: 57.00 Max.nchar: 9
## Max. :227.00 Max. :41 Max. :124.00
## Interpretación de Resultados para la Toma de Decisiones
Los indicadores calculados a partir de los **111,488 registros reales** aportan métricas objetivas para la auditoría de procesos hospitalarios:
* **Diagnóstico del Tiempo de Espera (`mean` vs `median`):**
* El tiempo medio de espera es de **15.38 minutos**, mientras que la mediana se sitúa en **14 minutos**.
* *Interpretación Gerencial:* Cuando la media es notablemente mayor que la mediana, significa que la distribución está sesgada a la derecha por culpa de unos pocos pacientes que sufren tiempos de espera extremadamente largos (outliers). El administrador no debe confiarse solo del promedio; debe investigar qué cuellos de botella específicos causan que el rango de espera vaya desde un mínimo de **0** hasta un máximo de **227 minutos**.
* **Evaluación de la Estandarización de Consultas (`sd` y `var`):**
* La duración de las citas presenta una desviación estándar de **3.218396\times 10^{4} minutos** (con una varianza de **1.0358071\times 10^{9}**).
* *Interpretación Gerencial:* La desviación estándar mide qué tanto se alejan los tiempos reales de consulta respecto al promedio programado. Una variabilidad alta indica que las citas no están estandarizadas (un médico puede tardar 5 minutos y otro 45 minutos con patologías similares). Para el administrador de agendas, reducir esta dispersión es clave para predecir con exactitud cuántos pacientes se pueden programar por hora sin sobresaturar las salas de espera.
* **Lectura Estratégica del `summary()`:**
* El resumen de la variable `age` (edad) permite identificar los percentiles de la población: el primer cuartil (25%) y el tercer cuartil (75%) delimitan el rango de edad donde se concentra el 50% de los usuarios activos. Esto ayuda a presupuestar insumos clínicos específicos.
* El resumen de la variable cualitativa `status` muestra directamente el volumen total de inasistencias en el histórico, sirviendo como indicador de línea base (KPI) para medir el éxito de futuras campañas de reducción de ausentismo.
---
## 7. Análisis de Estadística Inferencial: Comparación de Medias con `t.test()`
En la administración de recursos sanitarios, los promedios descriptivos no siempre reflejan la realidad absoluta. Si observamos que un grupo de pacientes espera más que otro, un buen gestor debe preguntarse: *¿Esta diferencia es estadísticamente significativa o se debe a la variabilidad natural del muestreo?*
La función `t.test()` aplica la **prueba t de Student**, una herramienta inferencial idónea para comparar las medias de dos grupos independientes y calcular **intervalos de confianza**.
### A. Planteamiento del Problema Sanitario
Como administradores, queremos evaluar si el **tiempo de espera (`waiting_time`)** antes de recibir atención médica difiere significativamente según el **sexo (`sex`)** del paciente. Para ello, planteamos las siguientes hipótesis estadísticas:
* **Hipótesis Nula (\(H_0\)):** El tiempo medio de espera es igual para pacientes hombres y mujeres (\(\mu_M = \mu_F\)).
* **Hipótesis Alternativa (\(H_1\)):** El tiempo medio de espera es diferente entre hombres y mujeres (\(\mu_M \neq \mu_F\)).
### B. Aplicación de la Prueba t en R
Utilizaremos la sintaxis de fórmula (`variable_numérica ~ variable_categórica`) para contrastar el indicador contra los dos grupos de género.
# Ejecutamos la prueba t de Student para muestras independientes
resultado_ttest <- t.test(waiting_time ~ sex, data = datos_citas, var.equal = FALSE)
# Mostramos el desglose completo de la prueba en el reporte
resultado_ttest##
## Welch Two Sample t-test
##
## data: waiting_time by sex
## t = -0.59638, df = 100721, p-value = 0.5509
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -0.3138133 0.1673934
## sample estimates:
## mean in group F mean in group M
## 20.03533 20.10854
---
## Interpretación de Resultados e Impacto en la Gestión
El análisis de la salida de la función `t.test()` nos provee de tres elementos clave para la toma de decisiones clínicas y operativas:
* **Evaluación del p-valor (Significancia Estadística):** El reporte nos devuelve un p-valor (p-value). En la práctica administrativa, si el **p-valor es menor a 0.05**, rechazamos la hipótesis nula (\(H_0\)). En este escenario simulado, el p-valor obtenido es de **0.5509**. Al ser mayor que 0.05, **no tenemos evidencia estadística para rechazar la hipótesis nula**. Esto significa que cualquier pequeña variación observada en los minutos de espera entre hombres y mujeres se debe puramente al azar y no a un sesgo institucional.
* **Análisis de las Medias de los Grupos:** La salida muestra de forma explícita la media estimada para cada grupo. El tiempo medio de espera para el sexo femenino (Group F) fue de **20.04 minutos**, mientras que para el sexo masculino (Group M) fue de **20.11 minutos**. Al ser valores prácticamente idénticos, confirmamos la equidad operativa en el flujo de atención.
* **Utilidad del Intervalo de Confianza del 95%:** El intervalo calculado para la diferencia de medias va desde **-0.31** hasta **0.17 minutos**. Debido a que este intervalo contiene al número **cero (0)**, se refuerza matemáticamente la conclusión de que no existe una diferencia real entre los dos géneros.
**Aplicación Gerencial:** Para un director de hospital, este resultado es una excelente noticia en términos de auditoría de calidad y equidad, ya que demuestra que el sistema de asignación de citas y salas de espera trata por igual a los pacientes independientemente de su sexo. Si el p-valor hubiera sido menor a 0.05 (indicando que un grupo esperaba significativamente más), el administrador tendría la obligación de auditar los procesos de admisión para erradicar cuellos de botella específicos o sesgos en la atención.
---
## 8. Análisis de Varianza (ANOVA) con `aov()` para Múltiples Grupos
Mientras que la prueba t de Student se limita a comparar dos grupos, en la gestión y administración sanitaria frecuentemente nos enfrentamos a escenarios con **tres o más categorías** (por ejemplo, comparar tiempos de atención entre múltiples especialidades médicas o evaluar la eficacia de diversos protocolos clínicos).
Para estos casos, la función `aov()` ejecuta un **Análisis de Varianza (ANOVA)**, permitiendo identificar si al menos uno de los grupos difiere significativamente de los demás.
### A. Planteamiento del Problema Sanitario
Como administradores de recursos sanitarios, queremos evaluar si el **tiempo de espera en sala (`waiting_time`)** varía de manera significativa según el **grupo de edad (`age_group`)** del paciente (el cual tiene 4 categorías: "0-18", "19-40", "41-65" y "65+").
* **Hipótesis Nula (\(H_0\)):** El tiempo medio de espera es idéntico en todos los grupos de edad (\(\mu_{0-18} = \mu_{19-40} = \mu_{41-65} = \mu_{65+}\)).
* **Hipótesis Alternativa (\(H_1\)):** Al menos un grupo de edad tiene un tiempo medio de espera diferente a los demás.
### B. Ejecución del ANOVA y la Prueba Post-Hoc en R
En R, estructuramos el modelo con la fórmula `variable_numérica ~ variable_categórica`. Dado que el ANOVA solo nos dice *si hay* diferencias pero no *dónde* están, aplicaremos adicionalmente la prueba de **Tukey (HSD)** con la función `TukeyHSD()` si el resultado es significativo.
# 1. Ajustamos el modelo de análisis de varianza (ANOVA)
modelo_anova <- aov(waiting_time ~ age_group, data = datos_citas)
# 2. Extraemos el resumen del modelo para ver el estadístico F y el p-valor
resumen_anova <- summary(modelo_anova)
resumen_anova## Df Sum Sq Mean Sq F value Pr(>F)
## age_group 3 2315 771.7 1.887 0.129
## Residuals 111484 45597800 409.0
# 3. Aplicamos la prueba de comparaciones múltiples de Tukey
post_hoc_tukey <- TukeyHSD(modelo_anova)---
## Interpretación de Resultados e Impacto en la Gestión
La lectura del cuadro de resultados del ANOVA provee la evidencia estadística necesaria para la optimización de procesos en clínicas y hospitales:
* **Interpretación del p-valor del ANOVA:** Al revisar la salida de `summary(modelo_anova)`, debemos fijarnos en la columna `Pr(>F)`. Si este p-valor general es **menor a 0.05**, se rechaza la hipótesis nula, concluyendo que la edad del paciente sí influye en el tiempo que pasa esperando en el centro médico. En nuestro modelo simulado, dado que los grupos se generaron con un comportamiento aleatorio homogéneo, el p-valor confirma si las diferencias observadas son estadísticamente significativas o no.
* **Uso Estratégico del Análisis Post-Hoc (Tukey):** Si el ANOVA global resulta significativo, el gestor sanitario recurre a la salida de `TukeyHSD(modelo_anova)`. Esta función compara los grupos por parejas (ej. "65+" contra "0-18") y calcula un p-valor ajustado para cada cruce.
**Aplicación Gerencial (Optimización del Flujo de Pacientes):**
* Si el análisis post-hoc revelara que el grupo **"65+" (Adultos Mayores)** presenta tiempos de espera significativamente más altos que el resto, el administrador de la institución de salud tendría una justificación técnica para reestructurar el proceso de admisión.
* Esto respaldaría la implementación de una **fila de triaje prioritaria** para la tercera edad o la asignación de asistentes de flujo clínico en horas pico, disminuyendo el riesgo de complicaciones asociadas a la espera prolongada en poblaciones vulnerables y mejorando directamente los indicadores de calidad percibida y satisfacción del usuario de salud.
---
## 9. Análisis de Variables Categóricas: Prueba de Chi-cuadrado con `chisq.test()`
En la administración y gestión de servicios de salud, no todas las variables de interés son numéricas. Frecuentemente trabajamos con atributos cualitativos (por ejemplo, el sexo del paciente, el tipo de seguro, el servicio médico asignado o si el paciente asistió o no a su cita).
Para determinar si existe una relación o asociación estadística entre dos variables categóricas, o si estas son completamente independientes, se utiliza la **Prueba de Chi-cuadrado de Pearson** a través de la función `chisq.test()`.
### A. Planteamiento del Problema Sanitario
Como administradores del centro médico, nos interesa evaluar si el ausentismo de los pacientes está asociado con su rango de edad. Específicamente, queremos saber si el estado de la cita (`status`: "Showed up" o "No Show") es independiente del grupo de edad al que pertenece el paciente (`age_group`).
* **Hipótesis Nula (\(H_0\)):** El estado de la cita (`status`) y el grupo de edad (`age_group`) son **independientes** (la edad no influye en la probabilidad de faltar a la cita).
* **Hipótesis Alternativa (\(H_1\)):** El estado de la cita y el grupo de edad están **asociados** (existe un comportamiento de ausentismo diferenciado según la edad del paciente).
### B. Aplicación de la Prueba de Chi-cuadrado en R
Para aplicar la función `chisq.test()`, primero debemos generar la tabla de contingencia (frecuencias absolutas) que cruza ambas variables categóricas utilizando la función `table()` que aprendimos en el punto 2.
# 1. Construimos la tabla de contingencia de frecuencias absolutas
tabla_contingencia <- table(datos_citas$status, datos_citas$age_group)
# 2. Ejecutamos la prueba de Chi-cuadrado de Independencia
resultado_chi2 <- chisq.test(tabla_contingencia)
# 3. Visualizamos el resultado de la prueba
resultado_chi2##
## Pearson's Chi-squared test
##
## data: tabla_contingencia
## X-squared = 1.4144, df = 3, p-value = 0.7022
---
## 10. Comparación de Proporciones entre Grupos con `prop.test()`
En la gestión de recursos sanitarios, evaluar el desempeño operativo o la calidad clínica a menudo implica comparar **tasas, porcentajes o proporciones** en lugar de promedios numéricos. Por ejemplo, un administrador puede necesitar comparar el porcentaje de reingresos hospitalarios entre dos unidades, o determinar si una campaña de vacunación fue más efectiva en una región que en otra.
La función `prop.test()` realiza una **prueba de igualdad de proporciones** (basada en la distribución Chi-cuadrado), calculando además el intervalo de confianza para la diferencia entre ambos porcentajes.
### A. Planteamiento del Problema Sanitario
Supongamos que la dirección de la red de salud quiere evaluar si el ausentismo hospitalario es equitativo entre géneros. Utilizando los datos reales del dataset, queremos determinar si la **proporción de ausentismo ("No Show")** de las pacientes del sexo **Femenino (F)** es significativamente diferente a la de los pacientes del sexo **Masculino (M)**.
* **Hipótesis Nula (H₀):** La proporción de ausentismo es igual en ambos sexos (\(p_F = p_M\)).
* **Hipótesis Alternativa (H₁):** La proporción de ausentismo es diferente entre ambos sexos (\(p_F \neq p_M\)).
### B. Aplicación de la Prueba de Proporciones en R
Para alimentar la función `prop.test()`, necesitamos pasarle dos vectores: uno con el número de "éxitos" o eventos de interés (en este caso, cuántos faltaron en cada sexo) y otro con el número total de ensayos (total de citas programadas por cada sexo). Primero, utilizaremos `table()` para extraer estos conteos de forma automática.
# 1. Creamos la tabla cruzada entre el estado de la cita y el sexo
tabla_ausentismo_sexo <- table(datos_citas$status, datos_citas$sex)
# 2. Extraemos el número de inasistencias ("No Show") para cada grupo (Fila "No Show")
# Nota: Ajusta el índice si en tu Excel el orden de las filas es distinto
exitos_noshow <- tabla_ausentismo_sexo["No Show", ]
# 3. Extraemos el total de citas programadas para cada sexo (Totales por columna)
totales_citas <- colSums(tabla_ausentismo_sexo)
# 4. Ejecutamos la prueba de igualdad de proporciones
resultado_proporciones <- prop.test(x = exitos_noshow, n = totales_citas, correct = FALSE)
# 5. Visualizamos el resultado
resultado_proporciones##
## 2-sample test for equality of proportions without continuity correction
##
## data: exitos_noshow out of totales_citas
## X-squared = 3.8771, df = 1, p-value = 0.04895
## alternative hypothesis: two.sided
## 95 percent confidence interval:
## -9.549475e-03 -1.526445e-05
## sample estimates:
## prop 1 prop 2
## 0.1982661 0.2030485
---
## Interpretación de Resultados y Utilidad en la Gestión Sanitaria
La salida de la función `prop.test()` proporciona la evidencia técnica requerida para la toma de decisiones sobre equidad y asignación de recursos:
* **Análisis del p-valor y Significancia:** Revisamos el `p-value` del reporte. Si el **p-valor es menor a 0.05**, rechazamos la hipótesis nula concluyendo que el sexo del paciente influye en la tasa de ausentismo. En esta simulación de **111,488 citas**, el p-valor nos indicará de manera contundente si las diferencias porcentuales observadas son estadísticamente significativas o simplemente variaciones marginales del muestreo.
* **Estimación de las Proporciones por Grupo (`sample estimates`):** Al final de la salida, R nos muestra los porcentajes estimados para cada grupo (Proportion 1 y Proportion 2). Esto le permite al administrador saber con precisión matemática cuál de los dos géneros presenta mayor propensión al incumplimiento de sus citas.
* **Intervalo de Confianza para la Diferencia:** El intervalo calcula el rango en el cual se encuentra la diferencia real entre ambas tasas (Proporción F - Proporción M). Si el intervalo incluye el valor **cero (0)**, confirma que las proporciones son estadísticamente equivalentes.
**Aplicación Gerencial:** Si la prueba demostrara que un sexo tiene una tasa de *No Show* significativamente más alta, la dirección del hospital podría diseñar políticas de comunicación diferenciadas. Por ejemplo, si los hombres faltaran más, se podrían pautar recordatorios telefónicos en horarios fuera de la jornada laboral o campañas de concientización sobre salud preventiva masculina, optimizando así la eficiencia de las agendas médicas y reduciendo el costo financiero de las horas de especialista subutilizadas.
---
## Interpretación de Resultados y Aplicación en la Gestión Sanitaria
La salida de la función `chisq.test()` nos proporciona los elementos necesarios para validar nuestras decisiones de planeación estratégica:
* **Interpretación del p-valor (Significancia Estadística):** Al igual que en las pruebas anteriores, el criterio de decisión clave es el **p-valor** (`p-value`). Si el p-valor obtenido es **menor a 0.05**, rechazamos la hipótesis nula (\(H_0\)) y aceptamos que existe una asociación real entre las variables en la población de estudio.
* **Análisis del Estadístico X-squared:** El valor de Chi-cuadrado (`X-squared`) mide qué tan diferentes son los datos reales observados en nuestro hospital respecto a los datos teóricos esperados si las variables fueran 100% independientes. Un valor alto de Chi-cuadrado suele empujar el p-valor hacia la significancia estadística.
**Aplicación Gerencial (Diseño de Estrategias Dirigidas):**
* Si la prueba arroja un p-valor menor a 0.05, el administrador sanitario tiene la certeza matemática de que **el ausentismo no se comporta igual en todas las edades**.
* Al inspeccionar los porcentajes por filas o columnas (utilizando el `prop.table()` aprendido previamente), el gestor puede descubrir, por ejemplo, si el grupo de adultos jóvenes ("19-40") es el que más falta por motivos laborales, o si los adultos mayores ("65+") tienen mayores tasas de *No Show* debido a barreras de movilidad o transporte.
* Con esta evidencia técnica, la dirección del hospital puede segmentar sus recursos: implementar recordatorios nocturnos vía SMS automatizados para el segmento joven y activar un programa de asignación de transporte social o telemedicina para la población de la tercera edad, maximizando la eficiencia de las agendas médicas y reduciendo el costo financiero de la capacidad oiciosa.
---
## 11. Visualización Científica y Comparativa Avanzada con `ggpubr`
En la alta gerencia de servicios de salud, la visualización de datos no solo debe ser estética, sino técnicamente concluyente. El paquete `ggpubr` facilita la creación de gráficos basados en `ggplot2` agregando de forma nativa comparaciones estadísticas (valores p, corchetes de significancia) directamente en el lienzo.
A continuación, se describen las variables del **Appointments Dataset** utilizadas para este análisis definitivo y se presentan tres gráficos interactivos clave.
### A. Descripción de las Variables Utilizadas
* **`waiting_time` (Numérica Continua):** Minutos transcurridos desde que el paciente realiza el check-in hasta que es atendido. Es el indicador de eficiencia operativa por excelencia.
* **`appointment_duration` (Numérica Continua):** Duración real en minutos de la consulta médica. Mide la intensidad del uso del recurso clínico.
* **`sex` (Categórica Nominal):** Género del paciente registrado ("F" para Femenino, "M" para Masculino).
* **`age_group` (Categórica Ordinal):** Clasificación del ciclo vital del paciente ("0-18", "19-40", "41-65", "65+").
* **`status` (Categórica Nominal):** Estado final de la cita programada ("Showed up" si asistió, "No Show" si se ausentó).
### Gráfico 1: Comparación del Tiempo de Espera por Sexo (Gráfico de Cajas / Boxplot)
Evaluamos la simetría y dispersión de los tiempos de espera entre hombres y mujeres, validando visualmente la prueba t efectuada en secciones previas.
# Creamos el gráfico base con ggpubr
g1_pubr <- ggboxplot(datos_citas, x = "sex", y = "waiting_time",
fill = "sex", palette = c("#EC407A", "#29B6F6"),
add = "jitter", alpha = 0.6, jitter.alpha = 0.05,
title = "Tiempos de Espera según Sexo del Paciente",
xlab = "Sexo", ylab = "Tiempo de Espera (Minutos)") +
theme_minimal()
# Lo transformamos en interactivo
ggplotly(g1_pubr)
**Comentario Estadístico y Gerencial (Gráfico 1):**
Al pasar el cursor sobre las cajas interactivas, el administrador puede observar la coincidencia casi exacta en las medianas, los cuartiles y la distribución general del tiempo de espera entre ambos sexos. Las líneas de dispersión (los "bigotes" de la caja) demuestran visualmente lo que calculó la prueba `t.test()` en el apartado 7: **no existen diferencias estadísticamente significativas en el flujo de atención por género**. Esto ratifica un proceso de admisión estandarizado y libre de sesgos en el servicio.
### Gráfico 2: Variación de la Duración de Citas por Grupo de Edad (Gráfico de Violín)
El gráfico de violín combina un diagrama de cajas con la curva de densidad, lo que nos permite ver con precisión dónde se concentra el volumen de minutos de atención en cada grupo demográfico.
```{rgráfico-ggpubr-2, warning=FALSE, message=FALSE}
g2_pubr <- ggviolin(datos_citas, x = "age_group", y = "appointment_duration",
fill = "age_group", palette = "npg",
add = "boxplot", add.params = list(fill = "white"),
title = "Densidad y Duración de Citas por Grupo de Edad",
xlab = "Grupo de Edad", ylab = "Duración de la Cita (Minutos)") +
theme_minimal()
ggplotly(g2_pubr)
``` r
g2_pubr<-ggviolin(datos_citas, x = "age_group", y = "appointment_duration",
fill = "age_group", palette = "npg",
add = "boxplot", add.params = list(fill = "white"),
title = "Densidad y Duración de Citas por Grupo de Edad",
xlab = "Grupo de Edad", ylab = "Duración de la Cita (Minutos)") +
theme_minimal()
ggplotly(g2_pubr)
Comentario Estadístico y Gerencial (Gráfico 2): La “anchura” de cada violín representa la densidad de probabilidad. Podemos notar visualmente que en todos los grupos de edad la mayor concentración de consultas se encuentra alrededor de los 20 minutos (la parte más ancha del violín). Sin embargo, al interactuar con las colas superiores de la gráfica, se hace evidente que los grupos de “41-65” y “65+” muestran una elongación mayor. Esto le indica al gestor que las consultas de pacientes adultos y de la tercera edad tienden a presentar mayor variabilidad operativa, requiriendo en la práctica médica real un margen de tiempo superior debido a la presencia de pluripatologías o comorbilidades.
Analizamos la frecuencia y variabilidad del ausentismo a lo largo de las distintas etapas de la vida para enfocar los recursos institucionales.
# Calculamos un resumen rápido para graficar medias de edad por estado de cita
df_resumen_barras <- datos_citas %>%
group_by(status, age_group) %>%
summarise(total_pacientes = n(), .groups = 'drop')
g3_pubr <- ggbarplot(df_resumen_barras, x = "age_group", y = "total_pacientes",
fill = "status", color = "white", palette = c("#E53935", "#4CAF50"),
label = TRUE, lab.col = "white", lab.pos = "in",
position = position_dodge(0.8),
title = "Volumen de Asistencia y Ausentismo por Segmento Etario",
xlab = "Grupo de Edad", ylab = "Cantidad Total de Citas") +
theme_minimal()
ggplotly(g3_pubr)Comentario Estadístico y Gerencial (Gráfico 3): Este gráfico interactivo de barras agrupadas segmenta visualmente el éxito o fracaso de la asistencia. Al pasar el cursor por las barras rojas correspondientes al “No Show”, el administrador sanitario puede cuantificar con precisión absoluta qué volumen de la pérdida de capacidad instalada se concentra en las edades productivas (“19-40” y “41-65”). Estratégicamente, esta es la gráfica que se le presenta a una junta directiva para justificar la inversión en un módulo automatizado de confirmación y sobreagendación, ya que permite visualizar el impacto nominal (número exacto de citas perdidas) que está sufriendo el hospital mes a mes.