Definição

O escore de propensão (Propensity Score Matching - PSM) é um cálculo que avalia a probabilidade do desfecho para cada participante e faz isso ao incluir neste cálculo um grupo de variáveis explicativas que pode influenciar essa probabilidade. 1 Esta técnica é necessária quando a amostra de um estudo não foi composta de forma aleatória. 2

Recomenda-se que as variáveis explicativas a serem incluídas no cálculo do escore de propensão apresentem:

  1. Potencial efeito como fator confundidor.
  2. Possibilidade de introdução de viés de seleção.

Utilizaremos o método de pareamento por vizinhos mais próximos para compor um grupo controle (sem o desfecho) mais homogêneo ao grupo caso (com o desfecho) em determinadas características com a finalidade de que, ao estimarmos o risco de óbito, este efeito não seja distorcido pela composição sistematicamente distinta dos grupos em relação a estas características. Entretanto, como a alocação não é aleatória, o pareamento por escore de propensão é mais precisamente um método quasi-experimental e indivíduos que não forem pareados são excluídos da análise. 3

Estudo de caso

Utilizaremos dados de casos confirmados de síndrome respiratória aguda grave (SRAG) causados por COVID-19 para identificar comorbidades que aumentaram o risco de óbito entre indivíduos com 18 anos ou mais hospitalizados em 2020 disponibilizados no data lake OpenDataSUS.

Download dos Dados

#--------- Pacotes

library(tidyverse)
library(MatchIt)
library(forestmodel)

#--------- Download

df <- read_csv2("https://s3.sa-east-1.amazonaws.com/ckan.saude.gov.br/SRAG/2020/INFLUD20-01-05-2023.csv")

O banco original possui 1199937 casos notificados e possui não apenas casos de COVID-19, mas também influenza, entre outros agentes etiológicos da SRAG.

Processamento dos Dados

df <- df |> 
  filter(CLASSI_FIN == 5,                                   # Casos de COVID-19
         HOSPITAL == 1) |>                                  # Hospitalizados
  mutate(CS_SEXO = case_when(CS_SEXO == "M" ~ "Masculino",
                             CS_SEXO == "F" ~ "Feminino"),
         DT_NOTIFIC = dmy(DT_NOTIFIC),
         DT_NASC = dmy(DT_NASC),
         IDADE = as.numeric(round((DT_NOTIFIC - DT_NASC) / 365.25, digits = 2)),
         CARDIOPATI = case_when(CARDIOPATI == 1 ~ "Presente",
                                CARDIOPATI == 2 ~ "Ausente"),
         DISPNEIA = case_when(DISPNEIA == 1 ~ "Presente",
                              DISPNEIA == 2 ~ "Ausente"),
         HEMATOLOGI = case_when(HEMATOLOGI == 1 ~ "Presente",
                                HEMATOLOGI == 2 ~ "Ausente"),
         HEPATICA = case_when(HEPATICA == 1 ~ "Presente",
                              HEPATICA == 2 ~ "Ausente"),
         ASMA = case_when(ASMA == 1 ~ "Presente",
                          ASMA == 2 ~ "Ausente"),
         DIABETES = case_when(DIABETES == 1 ~ "Presente",
                              DIABETES == 2 ~ "Ausente"),
         PNEUMOPATI = case_when(PNEUMOPATI == 1 ~ "Presente",
                                PNEUMOPATI == 2 ~ "Ausente"),
         IMUNODEPRE = case_when(IMUNODEPRE == 1 ~ "Presente",
                                IMUNODEPRE == 2 ~ "Ausente"),
         RENAL = case_when(RENAL == 1 ~ "Presente",
                           RENAL == 2 ~ "Ausente"),
         OBESIDADE = case_when(OBESIDADE == 1 ~ "Presente",
                               OBESIDADE == 2 ~ "Ausente"),
         EVOLUCAO = factor(EVOLUCAO, 
                           levels = c(1,2,3),
                           labels = c("Cura", "Óbito", "Óbito"),
                           ordered = TRUE)) |> 
  select(CS_SEXO, IDADE, CARDIOPATI, DISPNEIA, HEMATOLOGI, HEPATICA,
         ASMA, DIABETES, PNEUMOPATI, IMUNODEPRE, RENAL, OBESIDADE, EVOLUCAO) |> 
  filter(IDADE >= 18) |>                      
  drop_na()

Dados ausentes não são permitidos para realização do escore de propensão. Após o processamento, chegamos a 236875 casos confirmados de SRAG por COVID-19 em indivíduos de 18 anos ou mais hospitalizados no ano de 2020. Você pode explorar o dataset abaixo.

rmarkdown::paged_table(df)

Escore de Propensão

Primeiro, utilizaremos uma função do pacote MatchIt para realizar o pareamento e a seleção de uma subamostra com a finalidade de eliminar potenciais vieses ao criar grupos homogêneos. Neste momento devemos incluir apenas as covariáveis que queremos parear, mas não as covariáveis que desejamos avaliar (comorbidades), porém, para o mesmo desfecho.

match <- matchit(EVOLUCAO ~ CS_SEXO + IDADE,
                 method = "nearest", data = df)

summary(match)
## 
## Call:
## matchit(formula = EVOLUCAO ~ CS_SEXO + IDADE, data = df, method = "nearest")
## 
## Summary of Balance for All Data:
##                  Means Treated Means Control Std. Mean Diff. Var. Ratio
## distance                0.4375        0.3487          0.6508     0.9834
## CS_SEXOFeminino         0.4366        0.4779         -0.0833          .
## CS_SEXOMasculino        0.5634        0.5221          0.0833          .
## IDADE                  70.4676       61.0920          0.6530     0.8491
##                  eCDF Mean eCDF Max
## distance            0.1198   0.2663
## CS_SEXOFeminino     0.0413   0.0413
## CS_SEXOMasculino    0.0413   0.0413
## IDADE               0.1122   0.2633
## 
## Summary of Balance for Matched Data:
##                  Means Treated Means Control Std. Mean Diff. Var. Ratio
## distance                0.4375        0.4166          0.1534     1.2496
## CS_SEXOFeminino         0.4366        0.4550         -0.0370          .
## CS_SEXOMasculino        0.5634        0.5450          0.0370          .
## IDADE                  70.4676       68.5633          0.1326     1.1971
##                  eCDF Mean eCDF Max Std. Pair Dist.
## distance            0.0250   0.1042          0.1534
## CS_SEXOFeminino     0.0184   0.0184          0.6876
## CS_SEXOMasculino    0.0184   0.0184          0.6876
## IDADE               0.0229   0.0957          0.2112
## 
## Sample Sizes:
##           Control Treated
## All        146230   90645
## Matched     90645   90645
## Unmatched   55585       0
## Discarded       0       0

O output apresenta 4 seções com informações distintas:

  1. Setup do modelo utilizado (fórmula)
  2. Avaliação das covariáveis em todo modelo (All Data)
  3. Avaliação das covariáveis em todo modelo (Matched Data)
  4. Comparação do tamanho de amostra (Sample Sizes)

Observe mais atentamente a seção que apresenta a sumarização das covariáveis do dataset inicial (All Data). Pertenceram ao sexo masculino 56,34% dos indivíduos que evoluíram para óbito (desfecho) e 52,21% dos indivíduos que evoluíram para cura. Os grupos (óbito X cura) apresentaram uma diferença média de 8,3% na proporção do sexo masculino.

Veja agora a mesma covariável na seção com os dados pareados (Matched Data). Temos uma manutenção na proporção de indivíduos do sexo masculino no grupo que evoluiu para óbito, porém, o grupo controle (cura) foi composto por uma proporção maior de indivíduos do sexo masculino, agora com 54,50%. Isso reduziu a diferença média para 3,7% na proporção do sexo masculino, deixando o grupo pareado um pouco mais homogêneo para esta característica. A título de exercício repita essa análise, mas agora para a covariável idade.

Na última seção descobrimos que o algoritmo fez o pareamento de 1:1, ou seja, reuniu um indivíduo que evoluiu para cura com características semelhantes de sexo e idade que um indivíduo que evoluiu para óbito, mas para isso precisou remover os não pareados do dataset.

Agora, aplicaremos uma função para produzir um novo dataset apenas com os indivíduos pareados por estas características.

pareado <- match.data(match)

Chegamos a um dataset com 236875 composto de casos pareados confirmados de SRAG por COVID-19 em indivíduos de 18 anos ou mais hospitalizados no ano de 2020 e agora podemos modelar um regressão logística binária para identificar quais comorbidades aumentaram o risco de óbito.

labelled::var_label(pareado) <- list(CARDIOPATI = "Doença cardiovascular", 
                                     DISPNEIA =  "Dispneia", 
                                     HEMATOLOGI = "Doença Hematológica", 
                                     HEPATICA =  "Doença Hepática", 
                                     ASMA =  "Asma", 
                                     DIABETES =  "Diabetes", 
                                     PNEUMOPATI =  "Pneumopatia", 
                                     IMUNODEPRE =  "Imunodepressão", 
                                     RENAL =  "Doença renal crônica", 
                                     OBESIDADE = "Obesidade")

forest_model(glm(EVOLUCAO ~ 
               CARDIOPATI +
               DISPNEIA +
               HEMATOLOGI +
               HEPATICA +
               ASMA +
               DIABETES + 
               PNEUMOPATI +
               IMUNODEPRE +
               RENAL +
               OBESIDADE,
             family = binomial(), 
             data = pareado))

Apenas doença cardiovascular não apresentou associação estatisticamente significativa (p<0,05) com óbito entre pacientes com 18 anos ou mais que desenvolveram SRAG por COVID-19 e foram hospitalizados no ano de 2020. Os dois maiores fatores de risco para óbito fora, respectivamente, doença renal crônica e dispneia. Indivíduos com doença renal crônica apresentaram risco de óbito 95% maior que indivíduos sem esta comorbidade. A presença da dispneia aumentou o risco de óbito em 86%.

Porém, como seriam os resultados sem a utilização do escore de propensão? Podemos descobrir isso rodando o mesmo modelo, mas no dataset inicial (sem o pareamento).

labelled::var_label(df) <- list(CARDIOPATI = "Doença cardiovascular", 
                                DISPNEIA =  "Dispneia", 
                                HEMATOLOGI = "Doença Hematológica", 
                                HEPATICA =  "Doença Hepática", 
                                ASMA =  "Asma", 
                                DIABETES =  "Diabetes", 
                                PNEUMOPATI =  "Pneumopatia", 
                                IMUNODEPRE =  "Imunodepressão", 
                                RENAL =  "Doença renal crônica", 
                                OBESIDADE = "Obesidade")

forest_model(glm(EVOLUCAO ~ 
               CARDIOPATI +
               DISPNEIA +
               HEMATOLOGI +
               HEPATICA +
               ASMA +
               DIABETES + 
               PNEUMOPATI +
               IMUNODEPRE +
               RENAL +
               OBESIDADE,
             family = binomial(), 
             data = df))

Teríamos afirmado que doença cardiovascular aumentou o risco de óbito em 22%. Além disso, observamos também uma considerável superestimação do efeito da doença renal crônica e uma leve subestimação no efeito da dispneia.

inicial <- df |>
  filter(CARDIOPATI == "Presente") |> 
  group_by(EVOLUCAO) |> 
  summarise(Inicial = mean(IDADE))


pareado |> 
  filter(CARDIOPATI == "Presente") |> 
  group_by(EVOLUCAO) |> 
  summarise(Pareado = mean(IDADE)) |> 
  left_join(inicial, by = "EVOLUCAO") |> 
  rename(Evolução = EVOLUCAO) |> 
  mutate(Diferença = round(Pareado - Inicial, digits = 0))
## # A tibble: 2 × 4
##   Evolução Pareado Inicial Diferença
##   <ord>      <dbl>   <dbl>     <dbl>
## 1 Cura        70.5    64.6         6
## 2 Óbito       72.5    72.5         0

Observe que o dataset pareado conseguiu formar grupos homogêneos para a covariável idade, enquanto que no dataset inicial havia uma diferença média de 6 anos, ou seja, indivíduos com doença cardiovascular que evoluíram para cura eram, em média, 6 anos mais jovens e isso fez parecer que a presença desta comorbidade aumentou o risco de óbito quando foi a idade mais avançada que o fez. Um belíssimo exemplo de viés de seleção.

Limitações

O escore de propensão é calculado utilizando como base variáveis observáveis, logo, se houverem diferenças intrínsecas que não foram quantificadas e essas diferenças se distribuírem de forma sistemática nos grupos o viés de selação não será eliminado pelo escore de propensão.

Referências


  1. Patino CM, Ferreira JC. Escores de propensão: uma ferramenta para ajudar a quantificar os efeitos de tratamento em estudos observacionais. J Bras Pneumol. 2017;43(2):86.86. https://cdn.publisher.gn1.link/jornaldepneumologia.com.br/pdf/2017_43_2_4_portugues.pdf↩︎

  2. Vieira F. Abordagem econométrica via escore de propensão. Laboratório de Aprendizado de Máquina em Finanças e Organizações (LAMFO, UNB), 10 mai. 2020. https://lamfo-unb.github.io/2020/05/10/Abordagem-econom%C3%A9trica-via-escore-de-propens%C3%A3o/↩︎

  3. Fiaccone RL, Augusto M. Inferência causal e escore de propensão. https://ebest.sei.ba.gov.br/download/rosimeire.pdf/↩︎