Cohort 연구의 종류

  • cohort : 특정 인구집단

  • cohort study의 종류

    1. 전향적 코호트 연구 (Prospective cohort study)

      • 대부분의 코호트 연구는 전향적 코호트 연구
        1) 특정인자 -> 질병발생에 미치는 영향을 연구
        2) 질병없는 연구대상자 모으기 = 위험요인 노출O + 위험요인 노출X 나누기
        3) 시간에 따라 follow up(추적조사)하기
        4) 위험요인 노출O = 질병O + 질병X 관찰( 그중에 몇명이 질병걸렸냐 )
        5) 위험요인 노출X = 질병O + 질병X 관찰( 그중에 몇명이 질병걸렸냐 )
    2. 후향적 코호트 연구 (Retrospective cohort study)

      • 기록을 통해 특정인자 노출여부 + 질병발생 여부 분석
        1) 자료 = 질병O + 질병X 나누기
        2) 질병O = 특정요인 노출O + 특정요인 노출X( 그중에 몇명이 특정요인 노출됬냐 )
        3) 질병X = 특정요인 노출O + 특정요인 노출X( 그중에 몇명이 특정요인 노출됬냐 )
    3. 코호트 연구의 장단점
      1) 장점 : 시간의 흐름에 따른 정보 + 다양한 요인 노출도 수집가능 + 질병위험도 산출
      2) 단점 : 추적조사 놓치기 쉬움 + 희귀질병시 추적기간 매우 길어짐 -> 편향이 생길 수 있음.

Propensity Score Matching(성향 점수 매칭) for 후향적 코호트 연구(환자-대조군 연구)

환자 대조군 연구(case control study)는 후향적 코호트 연구에 속하며,

  1. 질병O(환자군)과 질병X(대조군)을 나눈 뒤,
  2. 각 군에 대해서 위험요인O + 위험요인X 나뉘는 것을 관찰한다.

그러나 RCT(Randomized Cotrolled Trial) - 무작위 대조군 실험과 같이 무작위 배정이 일어나지 않으므로, 편향이 생길 수 있다. 이 때, 사용하는 개념이 매칭이다.


매칭에는 빈도매칭(전체적인 특성 맞추기 - 연령 등)과 대응매칭(개인적인 특성 맞춤)으로 나뉠 수 있다.


여기서는 성향점수매칭을 이용하여, n수가 적은 환자군에 비해 n수가 너무 많아 bias가 포함되어있는 대조군을 매칭 시켜줄 것이다.


후향적 코호트 연구(환자-대조군 연구)에서는

  1. 환자군(Case군, n수 적음)과 대조군(Control군, n수 많음)은 n수 차이로 인해 base characteristics(기본특성)이 맞지 않아, 선택 편향(slection bias)이 발생한다.

  2. Case군의 임상적 특징을 갖는 대상을 control군내에서 골라내어 맞추는 작업이 필요하다

    • 환자군 100명, 대조군 900명의 unbalanced data라면, 대조군 900명 중 환자군과 유사한 사람 100명을 뽑아서 맞춰주어야한다.
  3. 이 때 . base성격(case군의 임상적특징)이 같은 여성을 뽑는 방법이 PSM이며, 공변량(공통 칼럼)의 수준을 맞춤으로서, 특정 독립변수가 종속변수에 미치는 영향을 파악할 수 있게 해준다.`

  4. 예시
    경구피임약이 유방암에 미치는 영향을 조사한다.
    1) Case : 유방암(질병O)이 발생한 여성
    2) Cotrol : 유방암이 발생하지 않은(질병X) 모든(X) base 성격이 유사한 여성


코드로 구현해보기

3-4. 후향적 코호트 연구(환자-대조군 연구)와 PSM

PSM(성향 점수 매칭)

  • 후향적 연구에서 n수가 많은 contrl(대조군) 중 case(환자군)과 base성격이 비슷한 것 뽑기
  • na값이 있으면 MatchIt 패키지가 작동하지 않으니 미리 제거해놓아야한다.
# install.packages("optmatch")
# library(optmatch) # 쓰이진 않았으나,, 흠..

# install.packages("MatchIt")
library(MatchIt)

# 1. 데이터 준비하기
library(moonBook)
acs2 <- na.omit(acs)

# 2. 데이터에서 case / contrl 가르기
# 데이터에서 환자군(case)과 대조군(control)를 가르기 위한 칼럼 생성해주기
#  -  acs2데이터 중에서 1) Dx가 "STEMI"  2) obesity가 Yes인 경우를 case군 1로 본다. 그렇않으면 control군으로서 0으로 본다.
#  -  ifelse (조건,   조건만족시 값,   조건불만족시의 값)
acs2$case_control <- ifelse( acs2$Dx == "STEMI" & acs2$obesity == "Yes", 1, 0)

# case/contrl분류 칼럼(범주형 칼럼) 확인 -> 범주 1개라도 table()로 범주형의 빈도 확인하기
table(acs2$case_control)
## 
##   0   1 
## 586  91
# 3. control군을 case군에 PSM 해주기 by age, sex, BMI로 ***절대 종속변수(폐암)과 특정요인(흡연)을 PSM기준으로 넣지 않는다!
# - MatchIt 패키지 - matchit()함수를 쓰며, method는 일단 "optimal"로 해준다.
# - case군 91건에 비해 ratio 3배로 뽑아 대조군 273건을 만든다. 기준은 3개의 공변량을 지정해줬다.
opt <- matchit( case_control ~ age + sex + BMI, method = "optimal", data = acs2, ratio = 3)
## Warning in optmatch::fullmatch(d, min.controls = ratio, max.controls = ratio, : Without 'data' argument the order of the match is not guaranteed
##     to be the same as your original data.
summary(opt) # 3개의 칼럼을 기준(보통 인구통계학적 칼럼)으로 매칭시킨 control군 273개, case 91개
## 
## Call:
## matchit(formula = case_control ~ age + sex + BMI, data = acs2, 
##     method = "optimal", ratio = 3)
## 
## Summary of balance for all data:
##           Means Treated Means Control SD Control Mean Diff eQQ Med
## distance         0.2629        0.1145     0.1284    0.1484  0.1269
## age             58.9780       63.7099    11.7782   -4.7319  5.0000
## sexFemale        0.2527        0.3413     0.4745   -0.0885  0.0000
## sexMale          0.7473        0.6587     0.4745    0.0885  0.0000
## BMI             27.4390       23.7060     3.2452    3.7330  3.3811
##           eQQ Mean eQQ Max
## distance    0.1468  0.2894
## age         4.7033  8.0000
## sexFemale   0.0879  1.0000
## sexMale     0.0879  1.0000
## BMI         3.7942  9.4500
## 
## 
## Summary of balance for matched data:
##           Means Treated Means Control SD Control Mean Diff eQQ Med
## distance         0.2629        0.1970     0.1490    0.0659  0.0582
## age             58.9780       59.9744    11.1096   -0.9963  1.0000
## sexFemale        0.2527        0.2308     0.4221    0.0220  0.0000
## sexMale          0.7473        0.7692     0.4221   -0.0220  0.0000
## BMI             27.4390       26.1883     2.6436    1.2507  1.3298
##           eQQ Mean eQQ Max
## distance    0.0671  0.1844
## age         1.4396  6.0000
## sexFemale   0.0220  1.0000
## sexMale     0.0220  1.0000
## BMI         1.3628  4.7419
## 
## Percent Balance Improvement:
##           Mean Diff. eQQ Med eQQ Mean eQQ Max
## distance     55.6152 54.1190  54.3272 36.3000
## age          78.9441 80.0000  69.3925 25.0000
## sexFemale    75.1800  0.0000  75.0000  0.0000
## sexMale      75.1800  0.0000  75.0000  0.0000
## BMI          66.4967 60.6702  64.0818 49.8212
## 
## Sample sizes:
##           Control Treated
## All           586      91
## Matched       273      91
## Unmatched     313       0
## Discarded       0       0
# 4. PSM을 거친 case(91)과 control(273)의 자료 opt 객체 안의 data만 뽑아보자.
# - 사실 이 자료들은 case(91)에 대해서, 3개의 기준칼럼간에 distance가 가까운 contol(273)을 뽑아준다.
# - case1 control 0으로 지정해놓았는데, 이것을 종속변수로한 로지스틱회귀분석을 통해 0 ~ 1사이의 확률을 distance로 보고,  control 0인 자료중 case 1에 가까운 자료들 273개를 뽑았을 것이다.
# - 결과적으로 distance( 0 ~ 1 확률) 칼럼도 생기는 것 같다.
opt.data <- match.data(opt)
head(opt.data)
##    age    sex cardiogenicShock   entry              Dx   EF height weight
## 1   62   Male               No Femoral           STEMI 18.0    168     72
## 5   56   Male               No  Radial          NSTEMI 21.8    162     64
## 6   73 Female               No  Radial Unstable Angina 22.0    153     59
## 7   58   Male               No  Radial Unstable Angina 24.7    167     78
## 9   59 Female               No  Radial Unstable Angina 28.5    152     67
## 12  52 Female               No  Radial Unstable Angina 31.1    156     63
##         BMI obesity  TC LDLC HDLC  TG  DM HBP   smoking case_control
## 1  25.51020     Yes 215  154   35 155 Yes  No    Smoker            1
## 5  24.38653      No 195  151   36  63 Yes Yes    Smoker            0
## 6  25.20398     Yes 184  112   38 137 Yes Yes     Never            0
## 7  27.96802     Yes 161   91   34 196 Yes Yes Ex-smoker            0
## 9  28.99931     Yes 239  161   34 118 Yes Yes     Never            0
## 12 25.88757     Yes 184  123   43  72 Yes Yes     Never            0
##      distance weights subclass
## 1  0.15417267       1        1
## 5  0.11760849       1       44
## 6  0.08791559       1       55
## 7  0.30317725       1       59
## 9  0.28675559       1       58
## 12 0.13214478       1        1

연습다시 해보기

  • acs -> 결측값 제거 -> acs3로 저장 -> ifelse 문으로 case/control 가르는 칼럼 지정 -> ratio 2배로 뽑아보기
  • 비만이 남자가 case , 그외 비만- 여자 + 비만x 남자 + 비만x 여자는 대조군
  • 추출변수(case와 맞춰줄 인구통계 변수)는 age, BMI
acs3 <- na.omit(acs)

acs3$case_control <- ifelse( acs3$obesity == "Yes" & acs3$sex == "Male", 1, 0)

table( acs3$case_control )
## 
##   0   1 
## 500 177
opt2 <- matchit( case_control ~ age + BMI, method = "optimal", data = acs3, ratio =2 )
## Warning in optmatch::fullmatch(d, min.controls = ratio, max.controls = ratio, : Without 'data' argument the order of the match is not guaranteed
##     to be the same as your original data.
summary(opt2) # case(Treated) 177 , contrl 354
## 
## Call:
## matchit(formula = case_control ~ age + BMI, data = acs3, method = "optimal", 
##     ratio = 2)
## 
## Summary of balance for all data:
##          Means Treated Means Control SD Control Mean Diff eQQ Med eQQ Mean
## distance        0.5679        0.1530     0.2052    0.4150  0.4297   0.4146
## age            57.5650       65.0240    11.6706   -7.4590  8.0000   7.4011
## BMI            27.3810       23.0844     2.9534    4.2966  3.9319   4.2867
##          eQQ Max
## distance  0.6091
## age      11.0000
## BMI       9.3978
## 
## 
## Summary of balance for matched data:
##          Means Treated Means Control SD Control Mean Diff eQQ Med eQQ Mean
## distance        0.5679        0.2109     0.2190    0.3570  0.3690   0.3586
## age            57.5650       62.4718    11.2119   -4.9068  5.0000   4.8418
## BMI            27.3810       24.3167     2.4533    3.0643  3.0018   3.0747
##          eQQ Max
## distance  0.5337
## age       8.0000
## BMI       5.0135
## 
## Percent Balance Improvement:
##          Mean Diff. eQQ Med eQQ Mean eQQ Max
## distance    13.9564 14.1371  13.5022 12.3878
## age         34.2169 37.5000  34.5802 27.2727
## BMI         28.6800 23.6552  28.2740 46.6523
## 
## Sample sizes:
##           Control Treated
## All           500     177
## Matched       354     177
## Unmatched     146       0
## Discarded       0       0
opt2.data <- match.data(opt2)
head(opt2.data)
##    age    sex cardiogenicShock   entry              Dx   EF height weight
## 1   62   Male               No Femoral           STEMI 18.0    168     72
## 5   56   Male               No  Radial          NSTEMI 21.8    162     64
## 6   73 Female               No  Radial Unstable Angina 22.0    153     59
## 7   58   Male               No  Radial Unstable Angina 24.7    167     78
## 9   59 Female               No  Radial Unstable Angina 28.5    152     67
## 12  52 Female               No  Radial Unstable Angina 31.1    156     63
##         BMI obesity  TC LDLC HDLC  TG  DM HBP   smoking case_control
## 1  25.51020     Yes 215  154   35 155 Yes  No    Smoker            1
## 5  24.38653      No 195  151   36  63 Yes Yes    Smoker            0
## 6  25.20398     Yes 184  112   38 137 Yes Yes     Never            0
## 7  27.96802     Yes 161   91   34 196 Yes Yes Ex-smoker            1
## 9  28.99931     Yes 239  161   34 118 Yes Yes     Never            0
## 12 25.88757     Yes 184  123   43  72 Yes Yes     Never            0
##     distance weights subclass
## 1  0.3028581       1        1
## 5  0.2291040       1       56
## 6  0.1643829       1       35
## 7  0.7171087       1       77
## 9  0.8211678       1       52
## 12 0.4871921       1      103

QUIZ - 1

  • 데이터(COPD_Lung_Cancer.csv)를 불러들이고 난후(df로 이름저장), 각 변수별 missing rate를 확인
  • mice 패키지의 md.pattern함수, VIM 패키지의 aggr함수 활용
  • is.na()활용
  • Missing rate가 5%가 넘는 변수는 제외하여 df2로 저장
getwd()
## [1] "C:/Users/is2js/R_da/myR"
# 불러오기
df <- read.csv('C:/Users/is2js/R_da/myR/week4/4주차_코드/COPD_Lung_Cancer.csv', header = T)
head(df)
##   PERSON_ID SEX DTH CTRB_PT_TYPE_CD   BMI BP_LWST BLDS TOT_CHOLE  HMG
## 1  10000065   1   0               8 25.73      90  112       177 12.2
## 2  10000183   1   0               9 22.77     100  105       177 15.7
## 3  10000269   1   0               8 24.54      70   76       156 13.1
## 4  10000471   1   0               1 21.63     100   70       228 14.0
## 5  10000788   2   0               7 25.65      54  113       199 12.1
## 6  10001096   2   0               3 19.84      60  137       182 12.0
##   FMLY_CANCER_PATIEN_YN SMK_STAT_TYPE DRNK_HABIT EXERCI_FREQ lungC copd
## 1                     1             1          1           1     0    0
## 2                     1             1          5           1     0    1
## 3                     1             1          1           1     1    1
## 4                    NA             1          1           1     0    1
## 5                     1             1          1           1     0    0
## 6                     1             1          1           1     0    0
##   Asthma DM Tub before_op_score after_op_score
## 1      0  1   0              44             52
## 2      1  1   0              44             53
## 3      0  1   1              37             60
## 4      0  1   0              50             44
## 5      1  1   0              31             43
## 6      0  0   0              34             49
# 전체 missing 값 확인
sum( is.na(df))
## [1] 228
# 전체 missing rate 확인
round( sum( is.na(df)) / (nrow(df) * ncol(df))   * 100 , 2)
## [1] 1.21
# 각 변수별 missing 개수 확인
apply( is.na(df), MARGIN = 2, FUN = "sum") 
##             PERSON_ID                   SEX                   DTH 
##                     0                     0                     0 
##       CTRB_PT_TYPE_CD                   BMI               BP_LWST 
##                     0                     0                     0 
##                  BLDS             TOT_CHOLE                   HMG 
##                     8                    10                     6 
## FMLY_CANCER_PATIEN_YN         SMK_STAT_TYPE            DRNK_HABIT 
##                    91                    44                    33 
##           EXERCI_FREQ                 lungC                  copd 
##                    36                     0                     0 
##                Asthma                    DM                   Tub 
##                     0                     0                     0 
##       before_op_score        after_op_score 
##                     0                     0
# 각 변수별 missing rate 확인
round( (apply( is.na(df), MARGIN = 2, FUN = "sum") / nrow(df) )* 100, 2)
##             PERSON_ID                   SEX                   DTH 
##                  0.00                  0.00                  0.00 
##       CTRB_PT_TYPE_CD                   BMI               BP_LWST 
##                  0.00                  0.00                  0.00 
##                  BLDS             TOT_CHOLE                   HMG 
##                  0.85                  1.06                  0.64 
## FMLY_CANCER_PATIEN_YN         SMK_STAT_TYPE            DRNK_HABIT 
##                  9.64                  4.66                  3.50 
##           EXERCI_FREQ                 lungC                  copd 
##                  3.81                  0.00                  0.00 
##                Asthma                    DM                   Tub 
##                  0.00                  0.00                  0.00 
##       before_op_score        after_op_score 
##                  0.00                  0.00
# mice패키지 - md.pattern()를 이용한 missing value 패턴확인
library(mice)
## Loading required package: lattice
## 
## Attaching package: 'lattice'
## The following object is masked from 'package:moonBook':
## 
##     densityplot
## 
## Attaching package: 'mice'
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
md.pattern(df)

##     PERSON_ID SEX DTH CTRB_PT_TYPE_CD BMI BP_LWST lungC copd Asthma DM Tub
## 794         1   1   1               1   1       1     1    1      1  1   1
## 81          1   1   1               1   1       1     1    1      1  1   1
## 8           1   1   1               1   1       1     1    1      1  1   1
## 4           1   1   1               1   1       1     1    1      1  1   1
## 11          1   1   1               1   1       1     1    1      1  1   1
## 2           1   1   1               1   1       1     1    1      1  1   1
## 2           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 7           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 20          1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 2           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 4           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
## 1           1   1   1               1   1       1     1    1      1  1   1
##             0   0   0               0   0       0     0    0      0  0   0
##     before_op_score after_op_score HMG BLDS TOT_CHOLE DRNK_HABIT
## 794               1              1   1    1         1          1
## 81                1              1   1    1         1          1
## 8                 1              1   1    1         1          1
## 4                 1              1   1    1         1          1
## 11                1              1   1    1         1          1
## 2                 1              1   1    1         1          1
## 2                 1              1   1    1         1          0
## 1                 1              1   1    1         1          0
## 7                 1              1   1    1         1          0
## 1                 1              1   1    1         1          0
## 1                 1              1   1    1         1          0
## 20                1              1   1    1         1          0
## 1                 1              1   1    1         1          0
## 2                 1              1   1    1         0          1
## 1                 1              1   1    1         0          1
## 1                 1              1   1    0         1          1
## 1                 1              1   1    0         0          1
## 4                 1              1   0    0         0          1
## 1                 1              1   0    0         0          1
## 1                 1              1   0    0         0          1
##                   0              0   6    8        10         33
##     EXERCI_FREQ SMK_STAT_TYPE FMLY_CANCER_PATIEN_YN    
## 794           1             1                     1   0
## 81            1             1                     0   1
## 8             1             0                     1   1
## 4             1             0                     0   2
## 11            0             1                     1   1
## 2             0             0                     1   2
## 2             1             1                     1   1
## 1             1             1                     0   2
## 7             1             0                     1   2
## 1             1             0                     0   3
## 1             0             1                     1   2
## 20            0             0                     1   3
## 1             0             0                     0   4
## 2             1             1                     1   1
## 1             1             1                     0   2
## 1             1             1                     0   2
## 1             1             1                     1   2
## 4             1             1                     1   3
## 1             1             1                     0   4
## 1             0             0                     1   5
##              36            44                    91 228
# VIM패키지 - aggr()을 이용한 missing value확인
library(VIM)
## Loading required package: colorspace
## Loading required package: grid
## Loading required package: data.table
## VIM is ready to use. 
##  Since version 4.0.0 the GUI is in its own package VIMGUI.
## 
##           Please use the package to use the new (and old) GUI.
## Suggestions and bug-reports can be submitted at: https://github.com/alexkowa/VIM/issues
## 
## Attaching package: 'VIM'
## The following object is masked from 'package:datasets':
## 
##     sleep
missing_pattern <- aggr(df)

missing_pattern$missings # aggr()의 값중에서도 $를 통해 missing value 개수를 빼낼 수 있음
##                                    Variable Count
## PERSON_ID                         PERSON_ID     0
## SEX                                     SEX     0
## DTH                                     DTH     0
## CTRB_PT_TYPE_CD             CTRB_PT_TYPE_CD     0
## BMI                                     BMI     0
## BP_LWST                             BP_LWST     0
## BLDS                                   BLDS     8
## TOT_CHOLE                         TOT_CHOLE    10
## HMG                                     HMG     6
## FMLY_CANCER_PATIEN_YN FMLY_CANCER_PATIEN_YN    91
## SMK_STAT_TYPE                 SMK_STAT_TYPE    44
## DRNK_HABIT                       DRNK_HABIT    33
## EXERCI_FREQ                     EXERCI_FREQ    36
## lungC                                 lungC     0
## copd                                   copd     0
## Asthma                               Asthma     0
## DM                                       DM     0
## Tub                                     Tub     0
## before_op_score             before_op_score     0
## after_op_score               after_op_score     0
missing_pattern$missings$Count # 칼럼의 순서를 기억하면서, 갯수만 빼낼 수 있다.
##  [1]  0  0  0  0  0  0  8 10  6 91 44 33 36  0  0  0  0  0  0  0
(missing_pattern$missings$Count / nrow(df) )* 100 # missing rate 5%이상은 10번째 칼럼
##  [1] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.8474576
##  [8] 1.0593220 0.6355932 9.6398305 4.6610169 3.4957627 3.8135593 0.0000000
## [15] 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
df2 <- df[,-c(1, 10)] # 앞에 -를 달아서, 해당것만 제외하고 인덱싱할 있다. 첫번째 칼럼은 id칼럼이라서 제외시킨다.
head(df2)
##   SEX DTH CTRB_PT_TYPE_CD   BMI BP_LWST BLDS TOT_CHOLE  HMG SMK_STAT_TYPE
## 1   1   0               8 25.73      90  112       177 12.2             1
## 2   1   0               9 22.77     100  105       177 15.7             1
## 3   1   0               8 24.54      70   76       156 13.1             1
## 4   1   0               1 21.63     100   70       228 14.0             1
## 5   2   0               7 25.65      54  113       199 12.1             1
## 6   2   0               3 19.84      60  137       182 12.0             1
##   DRNK_HABIT EXERCI_FREQ lungC copd Asthma DM Tub before_op_score
## 1          1           1     0    0      0  1   0              44
## 2          5           1     0    1      1  1   0              44
## 3          1           1     1    1      0  1   1              37
## 4          1           1     0    1      0  1   0              50
## 5          1           1     0    0      1  1   0              31
## 6          1           1     0    0      0  0   0              34
##   after_op_score
## 1             52
## 2             53
## 3             60
## 4             44
## 5             43
## 6             49

QUIZ - 2

  • df2에서 ifelse를 활용하여 1,0 생성(criteria 변수 : BMI>25 & DM=1인 값)
  • Sex, BMI, BP_LWST가 비슷한 환자군 고르기
  • 1:2 ratio
# ifelse : y/n형태로 범주화칼럼을 생성해서 0:대조군 1:환자군(case)를 만든다.
df2$case_contorl <- ifelse( df2$BMI > 25 & df2$DM == 1,   1, 0)

# PSM전에는 missing value가 있으면 안된다.
df2<-na.omit(df2)

# MatchIt 패키지 - matchif()함수로 , 기준칼럼들을 기준으로 환자군과 비슷한 대조군을 1:2배율로 뽑아낸다
library(MatchIt)
opt <- matchit( case_contorl ~ SEX + BMI + BP_LWST,
             method = "optimal",
             data = df2,
             ratio = 2)
## Warning in optmatch::fullmatch(d, min.controls = ratio, max.controls = ratio, : Without 'data' argument the order of the match is not guaranteed
##     to be the same as your original data.
# 뽑힌 대조군(2:1)환자군 수 확인
summary(opt)
## 
## Call:
## matchit(formula = case_contorl ~ SEX + BMI + BP_LWST, data = df2, 
##     method = "optimal", ratio = 2)
## 
## Summary of balance for all data:
##          Means Treated Means Control SD Control Mean Diff eQQ Med eQQ Mean
## distance        0.5453        0.0888     0.1751    0.4564   0.427   0.4548
## SEX             1.6573        1.5628     0.4964    0.0945   0.000   0.0979
## BMI            26.9328       21.8550     2.8444    5.0778   4.560   5.0863
## BP_LWST        81.2238       81.0464    12.0707    0.1773   0.000   0.9580
##          eQQ Max
## distance  0.7382
## SEX       1.0000
## BMI      12.3900
## BP_LWST  15.0000
## 
## 
## Summary of balance for matched data:
##          Means Treated Means Control SD Control Mean Diff eQQ Med eQQ Mean
## distance        0.5453        0.2119     0.2314    0.3334  0.3204   0.3350
## SEX             1.6573        1.5490     0.4985    0.1084  0.0000   0.1119
## BMI            26.9328       24.5638     1.7015    2.3690  2.2900   2.3844
## BP_LWST        81.2238       81.9441    12.3441   -0.7203  0.0000   0.9371
##          eQQ Max
## distance  0.5623
## SEX       1.0000
## BMI       3.0600
## BP_LWST  15.0000
## 
## Percent Balance Improvement:
##          Mean Diff. eQQ Med eQQ Mean eQQ Max
## distance    26.9584 24.9694  26.3326 23.8321
## SEX        -14.6987  0.0000 -14.2857  0.0000
## BMI         53.3451 49.7807  53.1210 75.3027
## BP_LWST   -306.1847  0.0000   2.1898  0.0000
## 
## Sample sizes:
##           Control Treated
## All           732     143
## Matched       286     143
## Unmatched     446       0
## Discarded       0       0
# 뽑은 데이터만 가져오기
opt.data <- match.data(opt)

nrow(opt.data) # 286 + 143 = 429
## [1] 429

+ Recent posts