3.1 Objetivos de aprendizaje

Al finalizar este capítulo, serás capaz de:

  • Definir confusión y sus consecuencias
  • Aplicar métodos de estratificación
  • Implementar matching (emparejamiento)
  • Utilizar ponderación por propensity score

3.2 ¿Qué es la confusión?

La confusión ocurre cuando una variable externa está asociada tanto con la exposición como con el resultado, distorsionando la estimación del efecto causal.

AdvertenciaConsecuencia

Sin control adecuado de la confusión, podemos:

  • Encontrar una asociación donde no existe efecto causal
  • No detectar un efecto causal real
  • Subestimar o sobreestimar la magnitud del efecto

3.3 Métodos para controlar confusión

3.3.1 1. Estratificación

La estratificación divide los datos en grupos homogéneos según el confusor.

# Simular datos
set.seed(123)
n <- 1000

# Confusor: edad (0 = joven, 1 = mayor)
edad <- rbinom(n, 1, 0.5)

# Exposición influenciada por edad
tratamiento <- rbinom(n, 1, 0.3 + 0.4 * edad)

# Resultado influenciado por ambos
resultado <- 50 + 10 * edad + 5 * tratamiento + rnorm(n, 0, 5)

datos <- data.frame(edad, tratamiento, resultado)

# Efecto crudo
cat("Efecto crudo:", 
    round(mean(resultado[tratamiento == 1]) - 
          mean(resultado[tratamiento == 0]), 2), "\n")
Efecto crudo: 9.01 
# Efecto estratificado
efecto_jovenes <- mean(resultado[tratamiento == 1 & edad == 0]) - 
                  mean(resultado[tratamiento == 0 & edad == 0])
efecto_mayores <- mean(resultado[tratamiento == 1 & edad == 1]) - 
                  mean(resultado[tratamiento == 0 & edad == 1])

cat("Efecto en jóvenes:", round(efecto_jovenes, 2), "\n")
Efecto en jóvenes: 4.7 
cat("Efecto en mayores:", round(efecto_mayores, 2), "\n")
Efecto en mayores: 5.17 

3.3.2 2. Matching (Emparejamiento)

El matching empareja individuos tratados y no tratados con características similares.

library(MatchIt)

# Datos más complejos
set.seed(456)
n <- 500

datos_match <- data.frame(
  edad = rnorm(n, 50, 10),
  imc = rnorm(n, 25, 5),
  sexo = rbinom(n, 1, 0.5)
)

# Probabilidad de tratamiento
prob_trat <- plogis(-2 + 0.05 * datos_match$edad + 
                    0.1 * datos_match$imc)
datos_match$tratamiento <- rbinom(n, 1, prob_trat)

# Resultado
datos_match$resultado <- 100 + 
  0.5 * datos_match$edad + 
  2 * datos_match$imc - 
  5 * datos_match$tratamiento + 
  rnorm(n, 0, 10)

# Matching
match_out <- matchit(tratamiento ~ edad + imc + sexo,
                     data = datos_match,
                     method = "nearest",
                     ratio = 1)

summary(match_out)

Call:
matchit(formula = tratamiento ~ edad + imc + sexo, data = datos_match, 
    method = "nearest", ratio = 1)

Summary of Balance for All Data:
         Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean
distance        0.9316        0.8815          0.9576     0.3455    0.2036
edad           51.4860       44.4794          0.7323     1.0378    0.1903
imc            25.1570       24.0066          0.2318     1.1417    0.0639
sexo            0.4871        0.4722          0.0297          .    0.0148
         eCDF Max
distance   0.3376
edad       0.3103
imc        0.1573
sexo       0.0148

Summary of Balance for Matched Data:
         Means Treated Means Control Std. Mean Diff. Var. Ratio eCDF Mean
distance        0.9887        0.8815          2.0500     0.0010    0.6529
edad           68.4310       44.4794          2.5033     0.2193    0.6264
imc            28.4034       24.0066          0.8859     0.9017    0.2409
sexo            0.5556        0.4722          0.1667          .    0.0833
         eCDF Max Std. Pair Dist.
distance   1.0000          2.0500
edad       0.9722          2.5033
imc        0.3889          1.3458
sexo       0.0833          0.8336

Sample Sizes:
          Control Treated
All            36     464
Matched        36      36
Unmatched       0     428
Discarded       0       0

3.3.2.1 Balance después del matching

Código
library(ggplot2)

plot(match_out, type = "jitter", interactive = FALSE)
Figura 3.1: Balance de covariables antes y después del matching

3.3.2.2 Estimación del efecto

# Obtener datos emparejados
datos_emparejados <- match.data(match_out)

# Efecto en datos emparejados
modelo_match <- lm(resultado ~ tratamiento, 
                   data = datos_emparejados,
                   weights = weights)

summary(modelo_match)$coefficients["tratamiento", ]
    Estimate   Std. Error      t value     Pr(>|t|) 
1.784918e+01 3.044303e+00 5.863141e+00 1.364022e-07 

3.3.3 3. Propensity Score

El propensity score es la probabilidad de recibir el tratamiento dado las covariables.

\[e(X) = P(T = 1 | X)\]

# Estimar propensity score
ps_model <- glm(tratamiento ~ edad + imc + sexo,
                data = datos_match,
                family = binomial)

datos_match$ps <- predict(ps_model, type = "response")

# Visualizar distribución
ggplot(datos_match, aes(x = ps, fill = factor(tratamiento))) +
  geom_density(alpha = 0.5) +
  labs(title = "Distribución del Propensity Score",
       x = "Propensity Score",
       fill = "Tratamiento") +
  theme_minimal()

3.3.4 4. Ponderación (IPTW)

La ponderación por el inverso del propensity score (IPTW) crea una pseudo-población donde tratamiento y covariables son independientes.

\[w_i = \frac{T_i}{e(X_i)} + \frac{1 - T_i}{1 - e(X_i)}\]

library(WeightIt)

# Calcular pesos
pesos <- weightit(tratamiento ~ edad + imc + sexo,
                  data = datos_match,
                  method = "ps",
                  estimand = "ATE")

summary(pesos)
                  Summary of weights

- Weight ranges:

          Min                                  Max
treated 1.004 ||                             1.498
control 2.467 |---------------------------| 53.778

- Units with the 5 most extreme weights by group:
                                          
            450    253    207    60     33
 treated  1.339  1.354  1.391 1.462  1.498
             27     24     21    14     13
 control 21.514 23.175 24.725 25.17 53.778

- Weight statistics:

        Coef of Var   MAD Entropy # Zeros
treated       0.063 0.045   0.002       0
control       0.715 0.492   0.208       0

- Effective Sample Sizes:

           Control Treated
Unweighted   36.    464.  
Weighted     24.04  462.18
# Modelo ponderado
modelo_iptw <- lm(resultado ~ tratamiento,
                  data = datos_match,
                  weights = pesos$weights)

summary(modelo_iptw)$coefficients["tratamiento", ]
   Estimate  Std. Error     t value    Pr(>|t|) 
-2.38609550  1.27698752 -1.86853471  0.06227447 

3.4 Comparación de métodos

Método Ventajas Desventajas
Estratificación Simple, transparente Solo para pocos confusores
Matching Intuitivo, balance visible Pérdida de muestra
PS Matching Reduce dimensionalidad Depende del modelo de PS
IPTW Usa toda la muestra Pesos extremos posibles

3.5 Diagnósticos importantes

3.5.1 Balance de covariables

Código
library(cobalt)

love.plot(pesos, 
          thresholds = c(m = 0.1),
          abs = TRUE,
          var.order = "unadjusted")
Figura 3.2: Love plot: comparación de balance

3.5.2 Distribución de pesos

summary(pesos$weights)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.004   1.033   1.063   1.955   1.119  53.778 
# Pesos extremos pueden indicar violación de positividad
cat("Pesos > 10:", sum(pesos$weights > 10), "\n")
Pesos > 10: 19 

3.6 Ejercicios

TipEjercicio 1

Usando el dataset simulado, compara los resultados de:

  1. Análisis crudo
  2. Matching por edad e IMC
  3. IPTW

¿Cuál se acerca más al efecto verdadero (-5)?

TipEjercicio 2

Evalúa el impacto de diferentes métodos de matching (nearest, optimal, genetic) en el balance y la estimación del efecto.

3.7 Resumen

  • La confusión distorsiona las estimaciones de efectos causales
  • La estratificación es útil para pocos confusores
  • El matching empareja individuos similares
  • El propensity score resume múltiples confusores en un solo número
  • IPTW permite usar toda la muestra
  • Siempre verificar el balance después del ajuste

Referencias