1. Introducción y Planteamiento del Problema

El presente análisis cuantitativo se centra en la evaluación de la satisfacción del paciente, un indicador clave de la calidad en la gestión sanitaria. Se busca ir más allá de los factores subjetivos, incorporando métricas funcionales objetivas.

1.1 Problema de Investigación

El estudio se centra en la Evaluación de la Satisfacción del Paciente utilizando un enfoque cuantitativo. El objetivo es identificar los determinantes más significativos y robustos de la satisfacción del paciente (medida en una escala de 1 a 10) a partir de una combinación de variables clínicas objetivas y factores demográficos/subjetivos, con el fin de informar la toma de decisiones administrativas en salud.

1.1.1 Pregunta de investigación

¿Qué combinación de métricas funcionales objetivas (frecuencia mínima de pasos y ángulo articular) y factores demográficos/subjetivos (edad, frecuencia de visita y calidad de vida) maximiza la precisión y la robustez en la predicción de la satisfacción del paciente, y cuáles son los umbrales clínicos óptimos para la intervención?

1.2 Descripción del Dataset

Los datos utilizados provienen de la base de datos de evaluación de salud comunitaria de Kaggle: community_health_evaluation_dataset.csv. Fuente de Datos: Community Health Evaluation Dataset (proveniente de Kaggle).

2. Exploración Analítica de Datos y Limpieza

2.1 Carga y Limpieza de Datos

El script comienza cargando los paquetes y realizando la limpieza inicial de la base de datos, estandarizando nombres y convirtiendo variables categóricas a factores para el análisis.

# =======================
# Paquetes
# =======================
library(tidyverse)
library(janitor)
library(MASS)
library(rpart)
library(rpart.plot)

# =======================
# Cargar datos
# =======================
data_raw <- read_csv("community_health_evaluation_dataset.csv")

# =======================
# Limpieza y preparación
# =======================
data_cleaned <- data_raw %>%
  clean_names() %>%
  mutate(
    patient_satisfaction = as.numeric(patient_satisfaction_1_10),
    age = as.numeric(age),
    quality_of_life_score = as.numeric(quality_of_life_score),
    gender = as.factor(gender),
    ses = as.factor(ses),
    service_type = as.factor(service_type),
    visit_frequency = as.factor(visit_frequency),
    emg_activity = as.factor(emg_activity)
  )

glimpse(data_cleaned)
## Rows: 347
## Columns: 13
## $ participant_id            <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1…
## $ age                       <dbl> 56, 69, 46, 32, 60, 25, 38, 56, 36, 40, 28, …
## $ gender                    <fct> F, M, M, F, M, F, F, F, F, F, M, M, F, F, M,…
## $ ses                       <fct> 4, 1, 4, 1, 3, 1, 3, 1, 3, 1, 2, 1, 1, 2, 4,…
## $ service_type              <fct> Rehab, Preventive, Rehab, Consultation, Prev…
## $ visit_frequency           <fct> Weekly, Yearly, Yearly, Weekly, Weekly, Year…
## $ step_frequency_steps_min  <dbl> 85, 80, 81, 66, 73, 74, 66, 68, 67, 82, 88, …
## $ stride_length_m           <dbl> 0.54, 0.70, 0.57, 0.78, 0.84, 0.90, 0.60, 0.…
## $ joint_angle               <dbl> 17.99, 13.05, 29.85, 28.54, 20.80, 26.84, 20…
## $ emg_activity              <fct> Low, Moderate, Moderate, Moderate, High, Hig…
## $ patient_satisfaction_1_10 <dbl> 1, 8, 4, 9, 5, 3, 9, 9, 4, 4, 8, 2, 9, 6, 9,…
## $ quality_of_life_score     <dbl> 57, 94, 66, 66, 98, 82, 81, 57, 68, 87, 52, …
## $ patient_satisfaction      <dbl> 1, 8, 4, 9, 5, 3, 9, 9, 4, 4, 8, 2, 9, 6, 9,…
# =======================
# Verificación
# =======================
str(data_cleaned)
## tibble [347 × 13] (S3: tbl_df/tbl/data.frame)
##  $ participant_id           : num [1:347] 1 2 3 4 5 6 7 8 9 10 ...
##  $ age                      : num [1:347] 56 69 46 32 60 25 38 56 36 40 ...
##  $ gender                   : Factor w/ 2 levels "F","M": 1 2 2 1 2 1 1 1 1 1 ...
##  $ ses                      : Factor w/ 4 levels "1","2","3","4": 4 1 4 1 3 1 3 1 3 1 ...
##  $ service_type             : Factor w/ 3 levels "Consultation",..: 3 2 3 1 2 1 2 1 3 3 ...
##  $ visit_frequency          : Factor w/ 3 levels "Monthly","Weekly",..: 2 3 3 2 2 3 1 2 3 1 ...
##  $ step_frequency_steps_min : num [1:347] 85 80 81 66 73 74 66 68 67 82 ...
##  $ stride_length_m          : num [1:347] 0.54 0.7 0.57 0.78 0.84 0.9 0.6 0.58 0.55 0.82 ...
##  $ joint_angle              : num [1:347] 18 13.1 29.9 28.5 20.8 ...
##  $ emg_activity             : Factor w/ 3 levels "High","Low","Moderate": 2 3 3 3 1 1 3 1 2 2 ...
##  $ patient_satisfaction_1_10: num [1:347] 1 8 4 9 5 3 9 9 4 4 ...
##  $ quality_of_life_score    : num [1:347] 57 94 66 66 98 82 81 57 68 87 ...
##  $ patient_satisfaction     : num [1:347] 1 8 4 9 5 3 9 9 4 4 ...
head(data_cleaned)
## # A tibble: 6 × 13
##   participant_id   age gender ses   service_type visit_frequency
##            <dbl> <dbl> <fct>  <fct> <fct>        <fct>          
## 1              1    56 F      4     Rehab        Weekly         
## 2              2    69 M      1     Preventive   Yearly         
## 3              3    46 M      4     Rehab        Yearly         
## 4              4    32 F      1     Consultation Weekly         
## 5              5    60 M      3     Preventive   Weekly         
## 6              6    25 F      1     Consultation Yearly         
## # ℹ 7 more variables: step_frequency_steps_min <dbl>, stride_length_m <dbl>,
## #   joint_angle <dbl>, emg_activity <fct>, patient_satisfaction_1_10 <dbl>,
## #   quality_of_life_score <dbl>, patient_satisfaction <dbl>

2.2 Estadísticas Descriptivas

Estadísticas descriptivas de las variables clave

summary(data_cleaned %>%dplyr::select(patient_satisfaction,age,quality_of_life_score,step_frequency_steps_min))
##  patient_satisfaction      age        quality_of_life_score
##  Min.   : 1.000       Min.   :18.00   Min.   :50.0         
##  1st Qu.: 3.000       1st Qu.:31.00   1st Qu.:62.0         
##  Median : 5.000       Median :43.00   Median :74.0         
##  Mean   : 5.213       Mean   :43.37   Mean   :74.2         
##  3rd Qu.: 8.000       3rd Qu.:56.00   3rd Qu.:86.0         
##  Max.   :10.000       Max.   :69.00   Max.   :99.0         
##  step_frequency_steps_min
##  Min.   :60.00           
##  1st Qu.:71.00           
##  Median :81.00           
##  Mean   :80.12           
##  3rd Qu.:90.00           
##  Max.   :99.00
# Visualización de la variable dependiente
ggplot(data_cleaned, aes(x = patient_satisfaction)) +
  geom_bar(fill = "steelblue") +
  labs(title = "Distribución de la Satisfacción del Paciente (1-10)", x = "Puntuación de Satisfacción", y = "Frecuencia") +
  theme_minimal()

Interpretación del histograma

El histograma de frecuencias muestra la distribución de las puntuaciones de satisfacción del paciente en una escala de 1 a 10. La frecuencia en el eje Y representa el número de pacientes que reportaron una puntuación específica eje X. La distribución de la satisfacción del paciente es irregular y multimodal, lo cual refleja que no existe un consenso claro en relación a un nivel de satisfacción único que domine en la población. La existencia de múltiples picos y la alta frecuencia de puntuaciones bajas (1.0 y 2.5) indican que la variable dependiente (patient_satisfaction) es difícil de predecir porque no sigue una tendencia única.

Modelo Matemático y Validación (Modelos 1 y 2)

Se incorporan el Modelo de Regresión Lineal Múltiple y la Regresión Logística Ordinal[cite: 7, 8].

3. Modelos de Predicción y Capacidad Explicativa/Predictiva

3.1 Modelo 1: Regresión Lineal Múltiple (MLR)

Objetivo: Explorar una relación lineal inicial entre la satisfacción y un conjunto de variables demográficas y subjetivas.

\[\text{Satisfacción} = \beta_0 + \beta_1 (\text{Age}) + \beta_2 (\text{SES}) + \beta_3 (\text{Service\_Type}) + \beta_4 (\text{Visit\_Frequency}) + \beta_5 (\text{EMG\_Activity}) + \epsilon\]

# Modelo 1: Regresión Lineal Múltiple
modelo_satisfaccion <- lm(
  patient_satisfaction ~ age + ses + service_type + visit_frequency + emg_activity,
  data = data_cleaned
)

# Resumen del modelo
summary(modelo_satisfaccion)
## 
## Call:
## lm(formula = patient_satisfaction ~ age + ses + service_type + 
##     visit_frequency + emg_activity, data = data_cleaned)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.7346 -2.2597 -0.1771  2.4607  5.2696 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             5.128147   0.646808   7.928 3.31e-14 ***
## age                     0.001289   0.010208   0.126    0.900    
## ses2                    0.207698   0.421612   0.493    0.623    
## ses3                    0.108648   0.420740   0.258    0.796    
## ses4                    0.439753   0.434187   1.013    0.312    
## service_typePreventive -0.030452   0.375404  -0.081    0.935    
## service_typeRehab      -0.371745   0.380520  -0.977    0.329    
## visit_frequencyWeekly   0.343736   0.381664   0.901    0.368    
## visit_frequencyYearly  -0.058679   0.384988  -0.152    0.879    
## emg_activityLow        -0.055399   0.382910  -0.145    0.885    
## emg_activityModerate   -0.265952   0.374001  -0.711    0.478    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.859 on 336 degrees of freedom
## Multiple R-squared:  0.01135,    Adjusted R-squared:  -0.01808 
## F-statistic: 0.3856 on 10 and 336 DF,  p-value: 0.9526
# Gráficos de diagnóstico
par(mfrow = c(2, 2))
plot(modelo_satisfaccion)

par(mfrow = c(1, 1))

Interpretación de Supuestos:

Los gráficos Residuals vs Fitted y Normal Q-Q sugieren que los supuestos de linealidad, homocedasticidad y normalidad de los residuos se cumplen.

GRÁFICO DE PREDICCIÓN

data_with_predictions <- data_cleaned %>%
  mutate(
    Predicted_Satisfaction = predict(modelo_satisfaccion),
    Residuals = residuals(modelo_satisfaccion)
  )

plot_prediccion <- ggplot(data_with_predictions, aes(x = patient_satisfaction, y = Predicted_Satisfaction)) +
  geom_point(alpha = 0.6, color = "darkred") +
  geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "blue", linewidth = 1) +
  labs(
    title = "Predicción del Modelo de Satisfacción del Paciente (MLR)",
    x = "Satisfacción Real (Observada) (1-10)",
    y = "Satisfacción Ajustada (Predicha por el Modelo)"
  ) +
  coord_cartesian(xlim = c(1, 10), ylim = c(1, 10)) + 
  theme_minimal()
print(plot_prediccion)

###Evaluación de Capacidad Predictiva (Modelo 1): Dado que los puntos están dispersos lejos de la línea azul diagonal, el modelo no tiene un alto poder predictivo, justificando el uso de modelos más fuertes.

3.2 Modelo 2: Regresión Logística Ordinal:

Se utiliza este modelo porque la variable dependiente (patient_satisfaction) es una escala ordinal (1 a 10).

Regresión Logística Ordinal

data_cleaned <- data_cleaned %>%
  mutate(patient_satisfaction_ord = factor(patient_satisfaction, ordered = TRUE))

modelo_ordinal <- polr(patient_satisfaction_ord ~ age + ses + service_type + visit_frequency + emg_activity, 
                       data = data_cleaned, 
                       Hess = TRUE) 
summary(modelo_ordinal)
## Call:
## polr(formula = patient_satisfaction_ord ~ age + ses + service_type + 
##     visit_frequency + emg_activity, data = data_cleaned, Hess = TRUE)
## 
## Coefficients:
##                            Value Std. Error  t value
## age                     0.001476   0.006273  0.23524
## ses2                    0.118201   0.256713  0.46044
## ses3                    0.063176   0.256893  0.24592
## ses4                    0.269664   0.265372  1.01617
## service_typePreventive -0.009192   0.228881 -0.04016
## service_typeRehab      -0.229356   0.234052 -0.97994
## visit_frequencyWeekly   0.208030   0.232312  0.89548
## visit_frequencyYearly  -0.047011   0.234822 -0.20020
## emg_activityLow        -0.022637   0.235060 -0.09630
## emg_activityModerate   -0.156813   0.227523 -0.68922
## 
## Intercepts:
##      Value   Std. Error t value
## 1|2  -1.8855  0.4196    -4.4933
## 2|3  -1.2506  0.4097    -3.0525
## 3|4  -0.6000  0.4052    -1.4806
## 4|5  -0.1916  0.4039    -0.4744
## 5|6   0.2779  0.4046     0.6869
## 6|7   0.6910  0.4066     1.6993
## 7|8   1.0847  0.4094     2.6493
## 8|9   1.7019  0.4166     4.0856
## 9|10  2.6523  0.4416     6.0064
## 
## Residual Deviance: 1584.211 
## AIC: 1622.211

Cálculo del Pseudo R^2 de McFadden

logL_modelo <- logLik(modelo_ordinal)
modelo_nulo <- polr(patient_satisfaction_ord ~ 1, data = data_cleaned, Hess = TRUE)
logL_nulo <- logLik(modelo_nulo)
R2_McFadden <- 1 - (logL_modelo / logL_nulo)
cat("\n--- Pseudo R^2 de McFadden ---\n")
## 
## --- Pseudo R^2 de McFadden ---
print(R2_McFadden)
## 'log Lik.' 0.002502743 (df=19)

Prueba de Razón de Verosimilitud (LRT) para Significancia Global

prueba_lrt <- anova(modelo_ordinal, update(modelo_ordinal, ~ 1), test = "Chisq")
cat("\n--- Prueba de Razón de Verosimilitud (LRT) ---\n")
## 
## --- Prueba de Razón de Verosimilitud (LRT) ---
print(prueba_lrt)
## Likelihood ratio tests of ordinal regression models
## 
## Response: patient_satisfaction_ord
##                                                       Model Resid. df
## 1                                                         1       338
## 2 age + ses + service_type + visit_frequency + emg_activity       328
##   Resid. Dev   Test    Df LR stat.   Pr(Chi)
## 1   1588.185                                
## 2   1584.211 1 vs 2    10 3.974821 0.9484757

###Evaluación de Capacidad Explicativa (Modelo 2): El R2 de McFadden es extremadamente bajo (0.0025) y la prueba LRT no rechaza la hipótesis nula (p-valor 0.948), lo que indica que el modelo no es estadísticamente significativo y que las variables elegidas inicialmente no explican la satisfacción.

3.2 Modelo Matemático y Validación (Modelos 3 y 4)

Aquí se introduce el modelo no lineal para buscar mayor poder predictivo.

4. Modelos de Predicción No Lineal (Máxima Capacidad Predictiva)

4.1 Modelo 3: Árbol de Decisión (Clasificación)

Justificación:
Se busca una relación no lineal, incluyendo variables funcionales y demográficas, para maximizar la capacidad predictiva de la satisfacción alta frente a la satisfacción baja.

library(rpart)
library(rpart.plot)
library(dplyr)

Preparación de la variable respuesta binaria

data_modeled <- data_cleaned %>%
  mutate(
    Satisfaccion_Alta_Bin = factor(
      ifelse(patient_satisfaction >= 9, "Alta", "Baja")
    )
  )

Fórmula del modelo

formula_arbol <- Satisfaccion_Alta_Bin ~
  age + ses + service_type + visit_frequency + emg_activity +
  quality_of_life_score + step_frequency_steps_min +
  stride_length_m + joint_angle

Ajuste del árbol de decisión

modelo_arbol <- rpart(
  formula_arbol,
  data = data_modeled,
  method = "class",
  control = rpart.control(minsplit = 20, cp = 0.01))

Visualización del árbol

rpart.plot(
  modelo_arbol,
  type = 4,
  extra = 101,
  main = "Árbol de Decisión: Predicción de Alta Satisfacción",
  nn = TRUE
)

4.1.1 Evaluación de Capacidad Predictiva (Modelo 3)

Matriz de Confusión y Accuracy

predicciones_arbol <- predict(modelo_arbol, data_modeled, type = "class")
matriz_confusion <- table(Real = data_modeled$Satisfaccion_Alta_Bin, Predicho = predicciones_arbol)
print(matriz_confusion)
##       Predicho
## Real   Alta Baja
##   Alta   28   30
##   Baja   14  275
accuracy_arbol <- sum(diag(matriz_confusion)) / sum(matriz_confusion)
cat("\n--- Precisión (Accuracy) del Modelo ---\n")
## 
## --- Precisión (Accuracy) del Modelo ---
print(accuracy_arbol)
## [1] 0.8731988

Interpretación del Árbol y Accuracy:

El Árbol de Decisión es el modelo más fuerte, alcanzando una Precisión (Accuracy) del 87.3% en la clasificación. Los predictores clave identificados para diferenciar la Satisfacción Baja y Alta son la Frecuencia Mínima de Pasos y el Ángulo de la Articulación, con umbrales específicos. La Matriz de Confusión indica que el modelo es muy bueno prediciendo la Satisfacción Baja (Verdaderos Negativos), pero omite casi la mitad de los casos de Satisfacción Alta.

4.2 Modelo 4: Regresión Logística Binomial:

Se utiliza el target binario (Satisfaccion_Alta) para intentar modelar la probabilidad, tomando las variables del árbol.

Regresión Logística Binomial

Se usa el dataframe limpio y modelado para asegurar consistencia

modelo_logistico_bin <- glm(
  Satisfaccion_Alta_Bin ~ quality_of_life_score + age + visit_frequency,
  data = data_modeled,
  family = binomial(link = "logit") 
)

summary(modelo_logistico_bin)
## 
## Call:
## glm(formula = Satisfaccion_Alta_Bin ~ quality_of_life_score + 
##     age + visit_frequency, family = binomial(link = "logit"), 
##     data = data_modeled)
## 
## Coefficients:
##                        Estimate Std. Error z value Pr(>|z|)  
## (Intercept)            1.747057   0.869580   2.009   0.0445 *
## quality_of_life_score -0.007677   0.010531  -0.729   0.4660  
## age                    0.011030   0.009637   1.144   0.2524  
## visit_frequencyWeekly -0.055187   0.356675  -0.155   0.8770  
## visit_frequencyYearly -0.056930   0.357484  -0.159   0.8735  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 313.23  on 346  degrees of freedom
## Residual deviance: 311.52  on 342  degrees of freedom
## AIC: 321.52
## 
## Number of Fisher Scoring iterations: 4

4.3 Odds Ratios (Ratios de Probabilidad)

exp(coef(modelo_logistico_bin))
##           (Intercept) quality_of_life_score                   age 
##             5.7376904             0.9923527             1.0110908 
## visit_frequencyWeekly visit_frequencyYearly 
##             0.9463085             0.9446606

Análisis:

Este modelo confirma que la Satisfacción Alta es difícil de predecir. El puntaje de Calidad de Vida no es significativo. La Edad tiene una relación marginal positiva, y el tipo de Frecuencia de Visita (semanal o anual) reduce las probabilidades de Satisfacción Alta en comparación con la base.

5. Interpretación de Resultados y Conclusiones

5.1 Interpretación de Resultados

El analisis secuencial de modelos nos permitió descartar relaciones lineales y ordinales débiles (MLR y Logística Ordinal), y converge en que el Árbol de Decisión (Modelo 3) es la herramienta más valiosa para la gestión, con una capacidad predictiva del 87.3%.

Los determinantes críticos de la satisfacción, según el Árbol, no son los factores demográficos o subjetivos (como la Calidad de Vida), sino las métricas funcionales objetivas: 1. Frecuencia Mínima de Pasos (\(step\_frequency\_steps\_min\)): Divisor principal del árbol. 2. Ángulo de la Articulación (\(joint\_angle\)): Segunda variable más importante.

5.2 Conclusiones a la Luz del Problema Planteado

Las conclusiones se estructuran como recomendaciones de gestión en salud basadas en la evidencia cuantitativa:

Recomendaciones de Intervención:

  • Enfoque Funcional: Los esfuerzos deben concentrarse en los factores identificados por el Árbol de Decisión. Se recomienda implementar programas que aseguren que los pacientes mantengan una Frecuencia Mínima de Pasos (cercana al umbral crítico de 89 pasos/min o más) y crear protocolos de seguimiento para Ángulos Articulares fuera de las zonas de riesgo (umbrales de \(13^{\circ}\) o \(23^{\circ}\) identificados).
  • Optimización de Recursos: La Calidad de Vida no es un predictor robusto de la satisfacción con el servicio, lo que sugiere que no se deben asumir ganancias automáticas. Los recursos deben enfocarse en resultados funcionales objetivos.
  • Frecuencia de Visita: Dado que más visitas no se asocian necesariamente con mayor satisfacción (e incluso tienen coeficientes negativos en la Logística Binomial), se recomienda optimizar las visitas presenciales, sustituyendo el exceso de visitas por monitoreo remoto cuando las métricas funcionales lo permitan.

Recomendaciones Futuras:

  • Mejora del Dataset: Se sugiere incluir variables de alto impacto funcional en futuros datasets para construir modelos más robustos.
  • Monitoreo Continuo: Adoptar un ciclo de “Medir - Analizar - Intervenir”, utilizando los umbrales de riesgo del Árbol de Decisión como puntos de activación para las intervenciones prioritarias.

```