이것저것/R 통계

[R 통계] 성향 점수 매칭 (Propensity score matching) - 1

엘:) 2024. 7. 16. 11:41
  • 후향적 연구를 하다보면 종종 성향 점수 매칭의 필요성을 느끼곤 합니다. 본 글에서는 R을 이용한 통계 분석에서 성향 점수 매칭을 하고 싶은 경우, 어떤 순서로 접근해야하는지 정리하고자 합니다.

 

성향 점수 매칭 (Propensity score matching, PSM)


  • 임상 연구에서는 무엇보다 연구자의 편향 (bias)을 줄여, 연구의 타당성을 확보하는 것이 중요합니다.
  • 무작위 대조 시험 (Randomized controlled trial, RCT) 을 설계하면 이러한 우려를 줄일 수 있지만, 윤리적 이슈, 비용, 가능성 등의 이유 때문에 모든 연구를 RCT로 수행할 수는 없습니다.
  • 관찰연구(Observational study) 시 큰 단점은 치료군과 대조군을 나눌 때 편향(bias)가 존재할 수 있다는 점입니다. (여기서 편향이란 특정 공변량에 의하여 연구 대상이 특정 처치를 받을 확률과 결과에 영향을 끼치는 것을 의미합니다.)
  • 정확히 치료 효과를 평가하기 위해서 성향 점수에 근거하여 균형 잡힌 각 군 간의 매칭(Matching)이 필요합니다. 이는 각 군에서 공변량의 수준을 맞는 짝(Pair)을 뽑아 매칭시키는 방법입니다.
  • PSM을 사용하면 관찰연구에 발생하는 편향을 줄이고 공변량의 영향을 통제할 수 있습니다.

  • 수행하고자 하는 분석의 방향과 데이터셋이 준비가 되었다면 위와 같은 과정으로 PSM을 진행하게 됩니다. 각 과정의 내용을 요약하면 아래와 같습니다.
  1. 데이터 준비 및 결측치 처리 (Data preparation & Checking missing values) : 분석 가설을 정의하고, 결측치를 처리하여 데이터셋을 준비합니다.
  2. 공변량 선택 (Selection of covariates) : 균형을 이루고자 하는 공변량을 선택합니다.
  3. 성향점수 평가 (Propensity score estimation) : 공변량에 근거하여 성향점수를 평가합니다.
  4. 매칭 (Data matching) : 여러 매칭 알고리즘 중 적합한 알고리즘을 택하여 성향점수에 근거해 군 간 쌍 (Pair) 를 만듭니다.
  5. 매칭 균형 평가 (Balance diagnostics) : 매칭이 적합하게 수행되었는지 군 간 균형을 평가합니다.
  6. 통계 분석 (Statistical analyses) : 군 간 통계 분석을 수행합니다.

 

 

 

 

 

  • 본 글에서도 아래 플로우를 따라 1번과 2번에 해당하는 결측치 처리와 공변량 선택을 설명드리겠습니다.

 

 

1. 데이터 준비 및 결측치 처리


  • 제가 이번 예시에서 사용할 데이터는 국민건강영양조사 (KNHANES) 의 22년도 자료입니다. (출처: https://knhanes.kdca.go.kr/knhanes/sub03/sub03_02_05.do)
  • 22년 자료 중 일부 변수 (흡연, 고혈압, 혈액 검사 변수) 만을 발췌하여 사용했습니다.
  • 분석에 쓰일 변수에 대하여 그것이 공변량 (Covariate) 인지, 치료 할당 변수(혹은 군을 구분하는 변수)인지, 결과 변수 (Outcome) 인지 구분해두고 목적을 세워두는 것이 좋습니다.
  • 본 실습에서는 가상으로 설정한 연구 목적은 아래와 같습니다.
흡연 여부에 따라 고혈압 진단 유무에 차이가 있는지 평가한다.

흡연 여부에 따른 군 할당 시, 혈액 검사 변수를 공변량으로 두고 성향 점수 매칭한 "흡연군" vs "비흡연군" 을 나누어 고혈압 진단 유무 차이를 분석한다.

 

요소 설명 비고
공변량 (C) 혈액 검사 변수 혈당, 콜레스테롤, 중성지방 등
치료 할당 변수 (T) 흡연 여부 평생 5갑 이상, 없음
결과 변수 (O) 고혈압 진단 유무 있음, 없음

 

 

 

library(MatchIt)
library(cobalt)
library(tableone)
library(moonBook)

data_raw = read.csv(file = 'KNHANES_data.csv')

str(data_raw) ## 6265 케이스, 30개 변수

## 5갑 미만, 비해당, 무응답 케이스 삭제
data_raw = data_raw[!(data_raw$Smoke == 8 | data_raw$Smoke == 9 | data_raw$Smoke == 1),] 
data_raw = data_raw[!(data_raw$HBP == 8 | data_raw$HBP == 9),]
  • 위에서 설명드린 KNHANES 원시자료를 저장해둔 CSV 데이터를 불러옵니다.
  • 우선 '치료 할당 변수' 는 binary 변수여야 합니다. Smoke 변수에서 '비해당, 무응답'에 해당하는 8, 9 와 '평생 5갑 미만 흡연'에 해당하는 1인 케이스는 삭제했습니다. (따라서 현재 [2 - 평생 5갑 이상], [3 - 피운 적 없음] 둘 중 하나인 케이스만 남긴 상태입니다.)
  • '결과 변수' 인 고혈압 진단 유무에서도 불필요한 '비해당, 무응답' 케이스는 삭제했습니다.
  • 'tableone' 과 'moonBook'은 결과를 요약하고 테이블을 만드는 library 인데 취향에 맞춰서 사용하시면 됩니다.

 

colSums(is.na(data_raw))

 

 

  • 전체 데이터셋에서 변수별로 결측치를 파악하는 다양한 방법이 있지만, 저는 위와 같이 변수별 결측치 개수를 파악했습니다.
  • 성향 점수 매칭 시 결측치가 있으면 안되므로 이와 같은 결측치를 미리 처리해야 합니다.

 

# 변수 선택하여 결측 케이스 제거
data = data_raw[complete.cases(data_raw[,c("Smoke", "HBP", "HE_glu", "HE_chol")]),]

# 모든 변수 결측 케이스 제거
data = na.omit(data_raw)

 

  • 결측치가 있는 케이스를 제거하는 방법은 크게 분석에 사용할 특정 변수만 선택하여 결측치가 있는 케이스를 삭제하는 방법과 모든 결측이 있는 케이스를 삭제하는 방법이 있습니다.
  • 케이스를 최대한 살리기 위해서는 불필요한 변수에 있는 결측치 때문에 케이스를 삭제하지 마시고, 변수를 선택하셔서 결측치를 삭제해야 합니다.
  • 이를 위해서는 분석에 사용할 변수를 특정하는 것도 중요한데, 이 부분은 아래 <2. 공변량 선택>에서 다루겠습니다.

 

## 결측치를 평균, 중앙값, 특정값으로 대체하는 방법
library(Hmisc)
x.Age.meanimp = impute(data$x.Age,mean)
x.Age.medimp = impute(data$x.Age,median)
x.Age.consimp = impute(data$x.Age,2)

## KNN imputation을 사용하는 방법
library(DMwR)
data.knnimp = knnImputation(data, k=10, meth = "weighAvg")

 

  • 위와 같이 결측치를 대체하는 방법도 존재합니다. 문헌에 따르면 아래와 같이 결측치 처리를 수행하라고 추천하고 있습니다.
1. 결측치가 거의 없다면  → 결측치 있는 케이스 제거
2. 그렇지 않다면 → 평균, 중앙값 등으로 결측치를 대체

 

  • 다른 결측치 처리 방법도 존재하지만 통계적 복잡성에 비해 해당 처리 방법이 PSM 수행에 적합한지 아직 논쟁의 여지가 있는 듯 합니다.

 

2. 공변량 선택


  • PSM을 수행하기 앞서 어떤 공변량을 군 간 비슷한 수준으로 맞출지에 대한 고민이 필요합니다.
  • 먼저 공변량을 C, 치료 할당 변수를 T, 결과 변수를 O 라고 가정해보겠습니다.
요소 설명 비고
공변량 (C) 혈액 검사 변수 혈당, 콜레스테롤, 중성지방 등
치료 할당 변수 (T) 흡연 여부 평생 5갑 이상, 없음
결과 변수 (O) 고혈압 진단 유무 있음, 없음

 

  • 공변량을 선택하기 위해서는 공변량과 치료 할당 변수, 결과 변수와의 관계를 고려해야 합니다. 이것은 정해진 법칙이 있다기보다는 해당 분야에 대한 기반 지식을 토대로 선택하는 것이므로, 연구자의 판단이 중요한 부분입니다. 예시를 들어보겠습니다.
  • 이해하기 쉽도록 C, T, O 의 관계를 그림으로 표현했고, 화살표의 방향이 C에서 O로 향한다면 'C가 O에 영향을 야기한다'는 의미입니다.

 

(A)

  • C가 T와 O에 모두 영향을 주는 경우입니다.
예를 들어, 피 수혈 여부 (T)가 사망률 (O) 에 영향을 끼치는지 알아보고자 할 때, C를 나이라고 가정합시다. 나이가 많을 수록 피 수혈 빈도도 잦아지고, 사망률도 높습니다.

이러한 나이 변수가 피 수혈 여부로 나눈 '수혈 군' vs '비수혈 군' 으로 나눴을 때 균형되지 않는다면 편향이 발생할 수 있습니다.

 

  • 따라서, 이런 경우 C를 공변량으로 사용해야 합니다.

 

(B)

  • C가 O에만 영향을 주는 경우입니다.
  • C와 T 사이에는 어떤 직접적인 관계가 없지만, 이러한 변수가 균형되지 않으면 O를 분석할 때 편향이 발생할 수 있습니다.
  • 따라서, 이런 경우 C를 공변량으로 사용해야 합니다.

 

(C)

  • C가 T에만 영향을 주는 경우입니다.
  • 이런 변수를 성향점수 매칭에 사용하는 경우 오히려 Variance를 높이고, 편향은 감소시키지 못한다고 알려져 있습니다.
  • 따라서, 이런 경우 C를 공변량으로 사용하면 안됩니다.

 

(D)

  • C가 T에게 영향을 받고, C가 또 O에만 영향을 주는, C가 T, O 사이에서 매개 역할을 하는 경우입니다. (가장 헷갈리기 쉬워 주의해야 하는 경우입니다.)
예를 들어, 제가 사용한 예제 처럼 흡연 여부 (T) 에 따른 고혈압 발병 (O) 을 알아보고자 할 때, C를 하루 니코틴 흡입량이라고 가정해봅시다. 당연히 흡연 그룹일수록 니코틴 흡입량이 많을 것입니다.

하지만 흡연 그룹 vs 비흡연 그룹 사이에 니코틴 흡입량이 균형되도록 설정하면 흡연, 비흡연 그룹을 나눈 의미가 퇴색되고 흡연 여부 (T) 의 효과가 제거되어 버립니다.

 

  • 따라서, 이런 경우 C를 공변량으로 사용하면 안됩니다.

 

 

 

  • 다음 글에서 공변량 선택 이후 성향점수 평가 부분을 다루도록 하겠습니다.

 

[References]

  1. Zhao, Qin-Yu, et al. "Propensity score matching with R: conventional methods and new features." Annals of translational medicine 9.9 (2021).
  2. Randolph, Justus J., and Kristina Falbe. "A step-by-step guide to propensity score matching in R." Practical Assessment, Research & Evaluation 19 (2014).
  3. Austin, Peter C. "An introduction to propensity score methods for reducing the effects of confounding in observational studies." Multivariate behavioral research 46.3 (2011): 399-424.