library(arrow)
library(broom.mixed)
# library(gutenbergr)
library(haven)
# library(labelled)
library(modelsummary)
library(rstanarm)
# library(tidybayes)
library(tidyverse)
library(tinytable)16 사후 층화 다단계 회귀 (MRP)
선수 지식
- 비대표적 여론 조사를 통한 선거 예측, (Wang et al. 2015)
- Xbox 플랫폼이라는 편향된 표본을 대상으로 MRP를 적용해 선거 결과를 예측한 사례를 다룹니다.
- 비대표적 설문 조사를 활용한 결혼 후 성(Surname) 변경 분석, (Alexander 2019)
- 설문 조사 데이터에 MRP를 구현하는 방법을 상세한 코드 및 데이터와 함께 제공합니다.
- 미스터 P(Mr. P)는 백신 주저 현상을 이해하는 데 도움이 됩니다, (Green 2020)
- MRP를 실전에 적용한 또 다른 사례로, 오픈 소스 코드와 데이터를 활용할 수 있습니다.
- 선거 결과의 통계적 모델, (Gelman 2020)
- 선거 예측 모델 구축 전반에 관한 논의를 담고 있습니다.
- 에피소드 248: 민주당은 비합리적인가? (데이비드 쇼어), (Galef 2020)
- 정치학에서 데이터가 어떻게 사용되는지 다루는 전반부에 집중해 보세요. 광범위하게 적용 가능한 통찰을 제공합니다.
핵심 개념 및 기술
- 사후 층화 다단계 회귀 (Multilevel Regression with Post-stratification, MRP)는 주로 대규모 여론 조사(비대표적 표본인 경우가 많음)를 사용해 모델을 훈련한 뒤, 이를 인구 조사 등의 사후 층화(Post-stratification) 데이터셋에 적용하는 기법입니다.
- 우리가 모델을 사용하는 이유는 데이터만으로는 직접 답할 수 없는 질문에 답하기 위해서입니다. 예를 들어, 전국의 모든 선거구에서 어떤 일이 일어나는지 알고 싶지만 모든 구역을 완벽하게 조사하기엔 비용이 너무 많이 듭니다. 만약 모든 구역의 완벽한 전수 데이터가 있다면 모델은 필요하지 않을 것입니다.
- 모델을 사용하면 데이터가 부족한 영역에 대해서도 답을 내놓을 수 있지만, 그만큼 불확실성(Uncertainty)이 뒤따릅니다. MRP 설정에서 모델은 데이터가 풍부한 영역에서 ‘정보를 빌려와(Borrowing information)’ 데이터가 거의 없는 영역의 추정을 돕습니다. 이러한 방식이 얼마나 타당한지는 분석가가 항상 고민해야 할 지점입니다. MRP의 가장 큰 현실적 난관 중 하나는 적합한 사후 층화 데이터셋을 확보하는 일입니다.
- MRP의 근본적인 가정은 성별, 연령대, 거주 지역 등 예측 변수와 결과(예: “누구에게 투표할 것인가?”) 사이의 관계가 설문 표본과 사후 층화 데이터셋(모집단 데이터) 사이에서 안정적으로 유지된다는 점입니다. MRP 추정 결과의 정당성을 판단할 때 가장 핵심적인 질문은 “이 가정이 얼마나 설득력 있는가?”입니다.
- 분석의 투명성은 매우 중요합니다. 설문 조사 원시 데이터는 보안상의 이유로 공개가 어려울 수 있지만, 데이터 전처리 및 모델링 코드는 결과와 함께 반드시 공개되어야 합니다. 이는 외부 전문가의 검증을 가능하게 하며, 분석 결과의 공신력을 높이는 핵심 요소입니다.
소프트웨어 및 패키지
- Base R (R Core Team 2024)
arrow(Richardson et al. 2023)broom.mixed(Bolker and Robinson 2022)gutenbergr(Johnston and Robinson 2022)haven(Wickham, Miller, and Smith 2023)labelled(Larmarange 2023)modelsummary(Arel-Bundock 2022)rstanarm(Goodrich et al. 2023)tidybayes(Kay 2022)tidyverse(Wickham et al. 2019)tinytable(Arel-Bundock 2024)
16.1 서론
[대통령 선거] 2016년은 미국 정치 역사상 가장 거대한 분석적 실패였습니다.
데이비드 쇼어(David Shor), 2020년 8월 13일
사후 층화 다단계 회귀(Multilevel Regression with Post-stratification, MRP)는 비대표적 설문 표본을 보정하여 여론이나 응답을 분석하는 매우 인기 있는 방법입니다. 이 기법은 회귀 모델을 통해 개인의 설문 응답을 다양한 특성과 연결한 뒤, 이를 바탕으로 표본을 재구성하여 모집단의 특징에 가깝게 맞춥니다. MRP를 활용하면 단순히 응답 현황을 파악하는 수준을 넘어, 데이터가 누락되거나 편향된 상황에서도 정교한 분석이 가능해집니다. 하지만 생소한 용어와 까다로운 데이터 요구 사항 때문에 처음 입문하기에는 다소 문턱이 높을 수 있습니다.
편향된 설문 상황을 가정해 봅시다. 예를 들어, 한 학술 대회에서 컴퓨터 브랜드 선호도를 조사한다면 ‘고학력자’ 집단이 과대 대표될 가능성이 큽니다. 하지만 우리는 일반 대중 전체의 선호도를 알고 싶어 합니다. 만약 응답자의 37.5%가 ‘맥(Mac)’을 선호한다고 응답했다면, 이를 그대로 믿고 “시장의 37.5%가 맥을 선호한다”고 결론 내리는 것은 위험합니다. 대신 우리가 가진 보조 정보를 활용해 보정할 수 있습니다. 예를 들어, ’석사 이상’ 그룹의 맥 선호도는 50%이고, ‘학사 이하’ 그룹은 25%라고 칩시다. 만약 실제 인구 통계상 석사 이상의 비율이 10%라면, 우리는 다음과 같이 가중치를 다시 매길 수 있습니다: \(0.5 \times 0.1 + 0.25 \times 0.9 = 0.275\). 즉, 전체 인구의 맥 선호 추정치는 27.5%가 됩니다.
MRP는 여기서 한 걸음 더 나아가, 다단계 로지스틱 회귀 모델을 통해 이러한 재가중 과정을 수행합니다. 이 방식의 가장 큰 장점 중 하나는 추정 과정에서의 불확실성을 통계적으로 훨씬 정교하게 설명할 수 있다는 점입니다. Clinton, Lapinski, and Trussler (2022) 등은 2020년 미국 대선 당시 민주당과 공화당 지지자 사이의 설문 응답률 차이를 이 기법으로 보정하여 여론 조사 오차를 크게 줄일 수 있음을 증명했습니다.
MRP는 Hanretty (2020) 의 설명처럼, 다른 대안이 제대로 작동하지 않거나 비용이 너무 많이 들 때 매우 유용한 도구가 됩니다. 핵심은 설문 데이터를 통해 모델을 ’훈련’시키고, 이 모델을 다른 대규모 데이터셋(모집단 데이터)에 ’적용’하는 것입니다. 다음과 같은 두 가지 결정적인 장점이 있습니다:
- 불확실성 관리 및 유연한 재가중: 소규모 표본이라 하더라도 단순히 데이터를 버리거나 더 수집하는 대신, 통계적 추론을 통해 정보를 최대한 활용할 수 있습니다.
- 세부 집단 추정(Small Area Estimation): 전국 단위에서는 대표성이 있는 설문이라 할지라도, 특정 주(state)나 연령대 수준으로 쪼개면 표본이 부족해지는 경우가 많습니다. MRP는 ‘정보를 빌려오는’ 메커니즘을 통해 이러한 세부 하위 집단에 대해서도 안정적인 추정치를 제공합니다.
현실적으로 확률 표본(Random sampling)을 구하는 것은 비용이 많이 들지만, 비확률 표본(편의 추출 등)은 상대적으로 수집이 용이합니다. 따라서 이를 유용하게 활용할 수 있는 MRP는 대단히 매력적인 도구입니다. 하지만 명심해야 할 점은, MRP가 모든 편향을 한 번에 날려버리는 ’마법의 지팡이’는 아니라는 사실입니다. 확률 표본을 직접 사용할 때보다 불확실성(표준 오차)은 당연히 커지며, 데이터 자체가 품고 있는 원천적인 편향(예: 특정 응답자의 성실도 등)에서 완전히 자유로울 수는 없습니다.
MRP 수행 과정은 논리적으로는 단순하지만, 각 단계에서 내려야 하는 결정들은 대단히 치밀해야 합니다. 결국 핵심은 두 데이터셋을 연결하는 다리를 놓는 것입니다. 기본적인 단계는 다음과 같습니다:
- 설문 데이터셋 준비: 사후 층화 데이터셋과 변수 및 범주가 일치하도록 가공합니다.
- 사후 층화 데이터셋 준비: (주로 인구 조사 데이터 등) 설문 데이터와 동일한 기준으로 분류합니다.
- 모델링: 설문 데이터를 활용해 예측 변수들과 결과 사이의 관계를 학습시킵니다.
- 적용: 훈련된 모델을 사후 층화 데이터셋의 각 층(Cell)에 적용하여 최종 추정치를 산출합니다.
유명한 MRP 적용 사례 중 하나는 Wang et al. (2015) 등이 Xbox 게임 플랫폼 데이터를 활용해 2012년 미국 대선 결과를 예측한 연구입니다. 이들은 선거 전 45일 동안 Xbox 플랫폼 내에서 자발적 참여 방식(opt-in)의 여론 조사를 실시했습니다. 매일 3~5개의 질문이 주어졌으며 “오늘 선거가 치러진다면 누구에게 투표하시겠습니까?”라는 유권자 의향 질문도 포함되었습니다. 응답자는 하루에 한 번만 참여할 수 있었고, 첫 응답 시 성별, 인종, 연령, 교육 수준, 거주 주, 지지 정당, 정치 성향, 2008년 투표 기록 등 상세한 개인 정보를 제공했습니다.
앤드류 겔만 박사는 컬럼비아 대학교의 통계학 및 정치학 석좌교수입니다. 1990년 하버드 대학교에서 통계학 박사 학위를 받은 후 UC 버클리를 거쳐 1996년부터 컬럼비아 대학교에서 연구를 이어오고 있습니다.
그의 연구는 통계학적 방법론과 사회과학의 접점에 깊이 뿌리내리고 있습니다. 특히 Wang et al. (2015) 등과의 연구는 “아무리 편향된 설문 데이터라도 통계적으로 적절히 다루면 귀중한 가치를 창출할 수 있음”을 보여주었습니다. 또한 그는 베이즈 통계 모델링에 널리 쓰이는 확률 프로그래밍 언어인 Stan의 핵심 설계자이기도 합니다.
그의 저서인 회귀 분석 및 다단계/계층 모델(Regression and Other Stories, Gelman and Hill)과 베이즈 데이터 분석(Bayesian Data Analysis, BDA)은 전 세계 수많은 데이터 과학자들에게 성서와 같은 영향을 끼쳤습니다. 2003년에는 통계학계의 노벨상이라 불리는 COPSS 회장상을 수상했습니다.
해당 연구에서는 총 345,858명의 고유 응답자로부터 750,148건의 인터뷰 데이터를 수집했습니다. 예상대로 Xbox 사용자는 젊은 남성이 압도적이었습니다. 18~29세 응답자가 전체의 65%에 달했는데, 이는 실제 대선 투표자 중 해당 연령층이 차지하는 비중(19%)보다 훨씬 높았습니다. 남성 응답자 비율 또한 93%로, 실제 유권자 비율인 47%를 크게 상회했습니다.
이들은 이러한 극단적인 편향을 바로잡기 위해 MRP를 적용했습니다. 핵심 원리는 거주 지역, 교육 수준, 성별 등 다양한 변수의 조합을 통해 특정 후보를 지지할 확률을 모델링하는 것입니다. 이렇게 ‘학습된’ 모델을 바탕으로 사후 층화(Post-stratification)를 수행합니다. 즉, 각 인구 통계학적 ’셀(cell)’에서 후보자가 얻을 표를 예측한 뒤, 실제 인구 비중에 맞춰 가중치를 부여해 전체(주 단위 혹은 전국 단위) 추정치를 계산하는 식입니다.
이를 위해서는 각 변수의 조합(예: 캘리포니아 거주, 20대, 대졸 남성)에 해당하는 실제 인구수를 알 수 있는 교차 집계(Cross-tabulated) 데이터가 반드시 필요합니다. 미국에서는 인구 조사(Census)나 ACS 데이터를 활용하는 것이 일반적입니다(Chapter 6). Wang et al. (2015) 은 출구 조사 데이터를 활용해 각 층의 인구 비중을 설정했습니다.
이들은 각 주의 특성을 반영한 사후 층화를 통해 주별 승패를 예측했고, 이를 선거인단 규모로 변환하여 최종 결과를 산출했습니다.
MRP는 강력한 만큼 고려해야 할 기회비용과 선택의 문제도 분명합니다. 예를 들어, Si (2020) 등은 어떤 모델링 접근 방식이 복잡한 데이터 구조를 가장 잘 포착하는지에 대해 심도 있게 논의했습니다. 또한 Lauderdale et al. (2020) 이나 Ghitza and Gelman (2020) 등은 설문 설계 단계의 불확실성이 최종 추정 결과에 미치는 영향을 연구했습니다.
이 장에서는 먼저 인구의 특징을 완벽히 알고 있다고 가정한 시나리오에서 시작해, 2020년 미국 대선 데이터를 활용한 실전 예측 모델까지 단계별로 살펴보겠습니다.
16.2 시뮬레이션 예시: 커피인가, 차인가?
16.2.1 모집단 생성 및 편향된 표본 추출
먼저 Chapter 8 에서 다루었던 ‘차 시음’ 실험으로 돌아가 봅시다. 여기서는 사람들이 커피와 차 중 무엇을 더 선호하는지에 대한 가상의 모집단을 시뮬레이션하겠습니다. 그 후 의도적으로 ’차를 선호하는 사람들’이 많이 뽑히도록 편향된 표본을 추출하고, MRP를 통해 다시 모집단의 진정한 선호도를 복원해낼 수 있는지 확인해 보겠습니다.
예측 변수로는 다음 두 가지를 사용합니다. - 연령대: “젊음(Young)” 또는 “고령(Old)” - 국적: “미국(US)” 또는 “영국(UK)”
시뮬레이션 규칙은 간단합니다. ’영국인’이거나 ’고령층’일수록 차를 더 선호할 확률이 높다고 설정하겠습니다. 실제 모집단은 각 그룹의 비율이 절반씩 균형을 이루고 있지만, 우리의 설문 조사는 고령의 영국인이 훨씬 더 많이 포함되도록 편향되게 설계할 것입니다. 물론 실제 데이터 분석에서는 ’진실’을 알 수 없지만, 이 시뮬레이션을 통해 MRP가 내부적으로 어떻게 작동하는지 명확히 이해할 수 있을 것입니다.
set.seed(853)
pop_size <- 1000000
sim_population <-
tibble(
age = rbinom(n = pop_size, size = 1, prob = 0.5),
nationality = rbinom(n = pop_size, size = 1, prob = 0.5),
probability = (age + nationality + 0.1) / 2.2, # 확률 0 또는 1 방지
prefers_tea = rbinom(n = pop_size, 1, prob = probability)
)
sim_population# A tibble: 1,000,000 × 4
age nationality probability prefers_tea
<int> <int> <dbl> <int>
1 0 1 0.5 0
2 0 0 0.0455 0
3 0 1 0.5 1
4 0 0 0.0455 0
5 0 0 0.0455 0
6 0 0 0.0455 0
7 0 1 0.5 0
8 0 0 0.0455 0
9 0 1 0.5 1
10 0 0 0.0455 0
# ℹ 999,990 more rows
각 하위 그룹별 인구 비중이 우리가 설정한 대로 고르게 구성된 것을 확인할 수 있습니다(Table 16.1).
sim_population |>
count(age, nationality, prefers_tea) |>
tt() |>
style_tt(j = 1:4, align = "lllr") |>
format_tt(digits = 0, num_mark_big = ",", num_fmt = "decimal") |>
setNames( c("연령", "국적", "차 선호", "수"))| 연령 | 국적 | 차 선호 | 수 |
|---|---|---|---|
| 0 | 0 | 0 | 238,568 |
| 0 | 0 | 1 | 11,319 |
| 0 | 1 | 0 | 125,371 |
| 0 | 1 | 1 | 124,730 |
| 1 | 0 | 0 | 125,438 |
| 1 | 0 | 1 | 124,723 |
| 1 | 1 | 0 | 11,421 |
| 1 | 1 | 1 | 238,430 |
전체 인구 중 약 50%가 차를 선호하도록 설계되었지만, 이 선호도는 인구 통계학적 하위 그룹에 따라 뚜렷하게 다르게 나타납니다.
이제 우리가 편향된 표본을 가진 설문 조사 데이터를 얻었다고 가정해 봅시다. 이 설문 조사는 고령층(Old)과 영국인(UK) 응답자가 더 많이 포함되도록 가중 표집(weighting)되었습니다. 과연 이 편향된 표본에서 산출된 차 선호도가 실제 모집단의 특성을 얼마나 왜곡하는지 살펴보겠습니다.
set.seed(853)
tea_sample <-
sim_population |>
slice_sample(n = 1000, weight_by = probability)tea_sample |>
count(age, nationality, prefers_tea) |>
tt() |>
style_tt(j = 1:4, align = "lllr") |>
format_tt(digits = 0, num_mark_big = ",", num_fmt = "decimal") |>
setNames(c("연령", "국적", "차 선호", "수"))| 연령 | 국적 | 차 선호 | 수 |
|---|---|---|---|
| 0 | 0 | 0 | 18 |
| 0 | 0 | 1 | 3 |
| 0 | 1 | 0 | 119 |
| 0 | 1 | 1 | 128 |
| 1 | 0 | 0 | 133 |
| 1 | 0 | 1 | 126 |
| 1 | 1 | 0 | 25 |
| 1 | 1 | 1 | 448 |
보시는 바와 같이, 우리 표본의 평균 차 선호도는 실제 모집단의 결과와 상당히 다르게 나타납니다(Table 16.2).
16.2.2 표본 모델링
이제 이 편향된 설문 데이터를 기반으로 모델을 ’훈련(training)’시킵니다. 연령과 국적을 예측 변수로 하여 차 선호도를 파악하는 모델을 구축합니다. 여기서는 각 하위 그룹의 효과를 정교하게 추정하기 위해 다단계 모델(Multilevel Model)을 사용합니다. 이 방식은 모든 데이터를 단순히 한데 묶어 평균을 내는 대신, 연령과 국적이라는 계층적 구조를 명시적으로 고려하여 정보를 효율적으로 결합하게 해줍니다.
\[ \begin{aligned} y_i|\pi_i & \sim \mbox{Bern}(\pi_i) \\ \mbox{logit}(\pi_i) & = \beta_0 + \alpha_{a[i]}^{\mbox{age}} + \alpha_{n[i]}^{\mbox{nat}} \\ \alpha_0 & \sim \mbox{Normal}(0, 2.5)\\ \alpha_{a}^{\mbox{age}} & \sim \mbox{Normal}\left(0, \sigma^2_{\mbox{age}}\right)\mbox{ for }a = 1, 2, \dots, A\\ \alpha_{n}^{\mbox{nat}} & \sim \mbox{Normal}\left(0, \sigma^2_{\mbox{nat}}\right)\mbox{ for }n = 1, 2, \dots, N\\ \sigma_{\mbox{age}} & \sim \mbox{Exponential}(1)\\ \sigma_{\mbox{nat}} & \sim \mbox{Exponential}(1) \end{aligned} \]
이 식에서 \(y_i\)는 개별 응답자의 차 선호 여부(0 또는 1)이며, \(\pi_i\)는 해당 응답자가 차를 선호할 확률입니다. \(\alpha^{\mbox{age}}\)와 \(\alpha^{\mbox{nat}}\)는 각각 연령 그룹과 국적 그룹이 주는 무작위 효과(Random effects)를 나타냅니다. 우리는 stan_glmer() 함수를 사용하여 베이즈 방식으로 모델을 추정합니다.
tea_preference_model <-
stan_glmer(
prefers_tea ~ (1 | age) + (1 | nationality),
data = tea_sample,
family = binomial(link = "logit"),
prior = normal(location = 0, scale = 0.5, autoscale = TRUE),
prior_intercept = normal(location = 0, scale = 0.5, autoscale = TRUE),
seed = 853
)
saveRDS(
tea_preference_model,
file = "tea_preference_model.rds"
)tea_preference_model <-
readRDS(file = "tea_preference_model.rds")modelsummary(
list(
"차 선호도 모델" = tea_preference_model
)
)| 차 선호도 모델 | |
|---|---|
| (Intercept) | 0.001 |
| Sigma[age × (Intercept),(Intercept)] | 2.171 |
| Sigma[nationality × (Intercept),(Intercept)] | 2.337 |
| Num.Obs. | 1000 |
| R2 | 0.261 |
| R2 Marg. | 0.000 |
| ICC | 0.7 |
| Log.Lik. | -457.970 |
| ELPD | -461.0 |
| ELPD s.e. | 16.2 |
| LOOIC | 921.9 |
| LOOIC s.e. | 32.4 |
| WAIC | 921.9 |
| RMSE | 0.39 |
?fig-teamodelresultsplots 는 모델을 통해 추정된 각 그룹별 사후 분포(Posterior distributions)를 보여줍니다.
tea_preference_model |>
spread_draws(`(Intercept)`, b[, group]) |>
mutate(condition_mean = `(Intercept)` + b) |>
ggplot(aes(y = group, x = condition_mean)) +
stat_halfeye() +
theme_minimal()16.2.3 사후 층화 데이터셋
이제 훈련된 모델을 적용할 사후 층화(Post-stratification) 데이터셋이 필요합니다. 이 데이터셋은 모집단의 구성을 정확하게 반영하고 있어야 합니다. 미국 분석가들은 주로 Chapter 6 에서 소개한 미국 지역사회 조사(ACS)를 활용하며, 다른 국가에서는 인구 조사(Census) 데이터를 가장 신뢰할 수 있는 사후 층화 자료로 사용합니다.
이 시뮬레이션 예제에서는 모집단 전체(100만 명)를 사후 층화 데이터로 사용할 수 있겠지만, 계산 효율성을 위해 그중 10,000명을 무작위로 추출하여 사용하겠습니다. 당연히 이 단계에서는 ‘차 선호도’ 정보를 모른다고 가정하고 해당 변수를 삭제합니다.
set.seed(853)
tea_poststrat_dataset <-
sim_population |>
slice_sample(n = 10000) |>
select(-prefers_tea)
tea_poststrat_dataset# A tibble: 10,000 × 3
age nationality probability
<int> <int> <dbl>
1 0 1 0.5
2 0 1 0.5
3 0 1 0.5
4 0 1 0.5
5 1 0 0.5
6 1 0 0.5
7 0 0 0.0455
8 1 0 0.5
9 1 0 0.5
10 1 0 0.5
# ℹ 9,990 more rows
이처럼 사후 층화 데이터셋에 개별 수준 정보가 완벽하게 구비되어 있다면, 모델을 각 개인에게 적용하여 결과를 산출할 수 있습니다.
predicted_tea_preference <-
tea_preference_model |>
add_epred_draws(newdata = tea_poststrat_dataset,
value = "preference") |>
ungroup() |>
summarise(
average_preference = mean(preference),
lower = quantile(preference, 0.025),
upper = quantile(preference, 0.975),
.by = c(age, nationality, .row)
)
predicted_tea_preference |>
count(age, nationality, average_preference)Table 16.4 는 MRP를 통해 얻은 최종 추정치를 실제 모집단의 수치(진실), 그리고 아무런 보정을 거치지 않은 편향된 표본의 수치와 비교해 보여줍니다. 실제 분석에서는 ’진실’을 알 수 없지만, 여기서는 MRP가 얼마나 강력하게 편향을 잡아내는지 확인할 수 있습니다.
comparison <- tibble(
Type = c("진실 (모집단)", "편향된 표본 (보정 전)", "MRP 최종 추정치"),
Estimate = c(
mean(sim_population$prefers_tea),
mean(tea_sample$prefers_tea),
mean(predicted_tea_preference$average_preference)
)
)
comparison |>
tt() |>
style_tt(j = 1:2, align = "lr") |>
format_tt(digits = 2, num_mark_big = ",", num_fmt = "decimal")보시는 바와 같이, MRP 기법은 심하게 편향된 설문 데이터를 사용했음에도 불구하고 모집단의 진정한 선호도를 매우 정확하게 복원해내는 데 성공했습니다.
16.3 2020년 미국 대통령 선거 예측
이번 분석에서는 Chapter 8 에서 소개한 민주주의 기금 유권자 연구 그룹(Democracy Fund Voter Study Group)의 여론 조사 데이터를 기반으로 모델을 구성하겠습니다. 그리고 사후 층화 데이터로는 Chapter 6 에서 다룬 IPUMS의 2019년 미국 지역사회 조사(ACS) 데이터를 활용합니다.
16.3.1 설문 조사 데이터: Nationscape
본 분석에서는 Nationscape 여론 조사 데이터셋을 사용합니다. MRP 실습에서 가장 까다로운 과정 중 하나는 설문 데이터와 사후 층화 데이터(인구 조사 등) 사이의 변수 정의를 완벽하게 일치시키는 작업입니다. 이를 위해 Chapter 8 에서 정제한 데이터를 불러온 뒤, 두 데이터셋이 같은 말을 하도록 텍스트 형식을 맞추는 전처리 과정을 진행합니다.
nationscape_data <-
read_csv(file = "nationscape_data.csv")nationscape_data# A tibble: 5,200 × 5
gender state vote_biden age_group education_level
* <chr> <chr> <dbl> <chr> <chr>
1 female WI 0 45-59 Post sec +
2 female VA 0 45-59 Post sec +
3 female TX 0 60+ High school or less
4 female WA 0 45-59 High school or less
5 female MA 1 18-29 Some post sec
6 female TX 1 30-44 Some post sec
7 female CA 0 60+ Some post sec
8 female NC 0 45-59 Post sec +
9 female MD 0 60+ Post sec +
10 female FL 1 45-59 Some post sec
# ℹ 5,190 more rows
# IPUMS와 일치하도록 주 이름 형식 지정
states_names_and_abbrevs <-
tibble(stateicp = state.name, state = state.abb)
nationscape_data <-
nationscape_data |>
left_join(states_names_and_abbrevs, by = "state")
rm(states_names_and_abbrevs)
# IPUMS 데이터와 일치하도록 소문자로 변경
nationscape_data <-
nationscape_data |>
mutate(stateicp = tolower(stateicp))
# NA를 DC로 대체
nationscape_data$stateicp <-
replace_na(nationscape_data$stateicp, "district of columbia")
# 클래스 정리
nationscape_data <-
nationscape_data |>
mutate(across(c(gender, stateicp, education_level, age_group),
as_factor))마지막으로, 준비된 데이터셋을 parquet 파일로 저장합니다.
write_parquet(x = nationscape_data,
sink = "nationscape_data_cleaned.parquet")사후 층화에 사용할 모집단 데이터를 선택할 때는 데이터의 신뢰도와 규모를 동시에 고려해야 합니다. 엄밀한 분석을 원한다면 Chapter 12 에서 언급한 협동 선거 연구(CES) 데이터가 좋겠지만, 이는 선거 후에 공개되므로 사전 예측용으로는 한계가 있습니다. 마찬가지로 Wang et al. (2015) 등이 사용한 출구 조사 데이터 역시 사후 분석용입니다.
따라서 Chapter 6 에서 수집한 2019년 미국 지역사회 조사(ACS) 데이터를 사후 층화의 모집단으로 활용하겠습니다.
poststrat_data# A tibble: 407,354 × 4
gender age_group education_level stateicp
* <fct> <fct> <fct> <fct>
1 male 60+ High school or less alabama
2 male 60+ Some post sec alabama
3 male 18-29 High school or less alabama
4 female 18-29 Some post sec alabama
5 male 30-44 Some post sec alabama
6 female 18-29 High school or less alabama
7 female 60+ High school or less alabama
8 female 18-29 Some post sec alabama
9 male 60+ High school or less alabama
10 male 45-59 High school or less alabama
# ℹ 407,344 more rows
이 데이터셋은 개별 수준 데이터로 이루어져 있습니다. 우리는 이를 바탕으로 각 하위 셀(성별, 연령, 교육, 주 등의 조합)의 빈도를 계산하고, 이를 주(state)별 인구 비중으로 변환할 것입니다.
poststrat_data_cells <-
poststrat_data |>
count(stateicp, gender, age_group, education_level)마지막으로 각 셀에 대한 비율을 추가합니다.
poststrat_data_cells <-
poststrat_data_cells |>
mutate(prop = n / sum(n),
.by = stateicp)
poststrat_data_cells# A tibble: 1,627 × 6
stateicp gender age_group education_level n prop
<fct> <fct> <fct> <fct> <int> <dbl>
1 connecticut male 18-29 High school or less 194 0.0419
2 connecticut male 18-29 Some post sec 128 0.0276
3 connecticut male 18-29 Post sec + 72 0.0156
4 connecticut male 18-29 Grad degree 14 0.00302
5 connecticut male 30-44 High school or less 132 0.0285
6 connecticut male 30-44 Some post sec 93 0.0201
7 connecticut male 30-44 Post sec + 147 0.0317
8 connecticut male 30-44 Grad degree 88 0.0190
9 connecticut male 45-59 High school or less 187 0.0404
10 connecticut male 45-59 Some post sec 88 0.0190
# ℹ 1,617 more rows
16.3.2 모델 구축 및 추정
조 바이든 후보와 도널드 트럼프 후보 중 누구를 지지하는지를 종속 변수로 하고, 성별, 연령대, 교육 수준, 그리고 거주 주(state)를 예측 변수로 하는 다단계 로지스틱 회귀 모델을 수립합니다.
\[ \begin{aligned} y_i|\pi_i & \sim \mbox{Bern}(\pi_i) \\ \mbox{logit}(\pi_i) & = \beta_0+ \alpha_{g[i]}^{\mbox{gender}} + \alpha_{a[i]}^{\mbox{age}} + \alpha_{s[i]}^{\mbox{state}} + \alpha_{e[i]}^{\mbox{edu}} \\ \beta_0 & \sim \mbox{Normal}(0, 2.5)\\ \alpha_{g}^{\mbox{gender}} & \sim \mbox{Normal}(0, 2.5)\mbox{ for }g=1, 2\\ \alpha_{a}^{\mbox{age}} & \sim \mbox{Normal}\left(0, \sigma^2_{\mbox{age}}\right)\mbox{ for }a = 1, 2, \dots, A\\ \alpha_{s}^{\mbox{state}} & \sim \mbox{Normal}\left(0, \sigma^2_{\mbox{state}}\right)\mbox{ for }s = 1, 2, \dots, S\\ \alpha_{e}^{\mbox{edu}} & \sim \mbox{Normal}\left(0, \sigma^2_{\mbox{edu}}\right)\mbox{ for }e = 1, 2, \dots, E\\ \sigma_{\mbox{gender}} & \sim \mbox{Exponential}(1)\\ \sigma_{\mbox{state}} & \sim \mbox{Exponential}(1)\\ \sigma_{\mbox{edu}} & \sim \mbox{Exponential}(1) \end{aligned} \]
여기서 \(y_i\)는 바이든을 지지할 경우 1, 그렇지 않을 경우 0의 값을 가집니다. 각 \(\alpha\) 항들은 각 변수가 투표 확률에 미치는 효과를 포착합니다. 특히 주와 교육 수준처럼 범주가 많은 변수들을 무작위 효과(Random effects)로 처리함으로써, 표본 수가 적은 주에서도 전국적인 트렌드로부터 정보를 ‘빌려와(Borrowing information)’ 안정적인 추정을 가능하게 합니다.
우리는 Kennedy and Gabry (2020) 의 코드를 참고하여, rstanarm 패키지의 stan_glmer() 함수로 모델을 추정하겠습니다.
nationscape_data <-
read_parquet(file = "nationscape_data_cleaned.parquet")us_election_model <-
stan_glmer(
vote_biden ~ gender + (1|age_group) + (1|stateicp) + (1|education_level),
data = nationscape_data,
family = binomial(link = "logit"),
prior = normal(location = 0, scale = 2.5, autoscale = TRUE),
prior_intercept = normal(location = 0, scale = 2.5, autoscale = TRUE),
cores = 4,
adapt_delta = 0.99,
seed = 853
)saveRDS(
us_election_model,
file = "us_election_model_mrp.rds"
)이 거대한 모델은 추정에 약 15분 정도 소요되므로, 계산이 완료되면 saveRDS() 함수를 사용해 별도의 파일로 저장해 두는 것이 좋습니다. 이후 분석에서는 readRDS()를 통해 즉시 불러와 사용할 수 있습니다.
us_election_model <-
readRDS(file = "us_election_model_mrp.rds")먼저 모델을 통해 추정된 각 변수별 계수들을 살펴보겠습니다(Table 16.5). 주별 무작위 절편(Random intercepts)과 다른 변수들의 효과가 어떻게 나타나는지 확인할 수 있습니다.
modelsummary(
us_election_model
)| (1) | |
|---|---|
| (Intercept) | 0.373 |
| gendermale | -0.542 |
| Sigma[stateicp × (Intercept),(Intercept)] | 0.081 |
| Sigma[education_level × (Intercept),(Intercept)] | 0.036 |
| Sigma[age_group × (Intercept),(Intercept)] | 0.241 |
| Num.Obs. | 5200 |
| R2 | 0.056 |
| R2 Marg. | 0.017 |
| ICC | 0.2 |
| Log.Lik. | -3434.075 |
| ELPD | -3468.0 |
| ELPD s.e. | 16.2 |
| LOOIC | 6936.1 |
| LOOIC s.e. | 32.4 |
| WAIC | 6936.0 |
| RMSE | 0.48 |
?fig-politicsmodelresultsplots 는 연령대와 교육 수준에 따른 지지율의 사후 분포를 보여줍니다. 또한 공간상의 제약으로 인해 일부 주요 주들을 선별하여 별도로 시각화했습니다(?fig-politicsmodelresultsplotsstates).
us_election_model |>
spread_draws(`(Intercept)`, b[, group]) |>
mutate(condition_mean = `(Intercept)` + b) |>
separate(col = group,
into = c("type", "instance"),
sep = ":", remove = FALSE) |>
filter(type != "stateicp") |>
ggplot(aes(y = group, x = condition_mean)) +
stat_halfeye() +
theme_minimal()us_election_model |>
spread_draws(`(Intercept)`, b[, group]) |>
mutate(condition_mean = `(Intercept)` + b) |>
separate(col = group, into = c("type", "instance"), sep = ":", remove = FALSE) |>
filter(type == "stateicp") |>
filter(instance %in%
c("california", "florida", "michigan", "new_york", "pennsylvania",
"vermont", "west_virginia", "wisconsin")
) |>
ggplot(aes(y = group, x = condition_mean)) +
stat_halfeye() +
theme_minimal()16.3.3 사후 층화 실행
이제 앞서 계산한 모집단 비율 데이터셋을 활용해 사후 층화를 수행합니다. 이 과정을 통해 각 주별로 가중치가 적용된 최종 지지율 추정치와 그에 따른 95% 신용 구간을 도출할 수 있습니다.
biden_support_by_state <-
us_election_model |>
add_epred_draws(newdata = poststrat_data_cells) |>
rename(support_biden_predict = .epred) |>
mutate(support_biden_predict_prop = support_biden_predict * prop) |>
ungroup() |>
summarise(support_biden_predict = sum(support_biden_predict_prop),
.by = c(stateicp, .draw)) |>
summarise(
mean = mean(support_biden_predict),
lower = quantile(support_biden_predict, 0.025),
upper = quantile(support_biden_predict, 0.975),
.by = stateicp
)
head(biden_support_by_state)산출된 주별 추정치를 시각화하여 실제 원시 데이터와 어떻게 다른지 비교해 보겠습니다(?fig-estimatyusamrp).
biden_support_by_state |>
ggplot(aes(y = mean, x = fct_reorder(stateicp, mean),
color = "MRP 추정치")) +
geom_point() +
geom_errorbar(aes(ymin = lower, ymax = upper), width = 0) +
geom_point(
data = nationscape_data |>
summarise(n = n(),
.by = c(stateicp, vote_biden)) |>
mutate(prop = n / sum(n),
.by = stateicp) |>
filter(vote_biden == 1),
aes(y = prop, x = stateicp, color = "Nationscape 원시 데이터")
) +
geom_hline(yintercept = 0.5, linetype = "dashed") +
labs(
x = "주 (State)",
y = "바이든 지지 추정 비중",
color = "데이터 출처"
) +
theme_classic() +
scale_color_brewer(palette = "Set1") +
coord_flip() +
theme(legend.position = "bottom")Nationscape는 매우 높은 품질의 설문 조사 데이터셋입니다. 하지만 주 단위가 아닌 주요 권역(서부, 중서부, 북동부, 남부) 중심으로 가중치가 설계되었기에, 주별 세부 추정치에서는 MRP 보정 결과와 원시 데이터 사이에 다소 차이가 발생할 수 있습니다. 이는 MRP가 특정 지역의 소규모 표본으로 인한 왜곡을 전국적 트렌드를 활용해 어떻게 조정하는지를 보여주는 좋은 예시이기도 합니다.
16.4 연습 문제
연습 문제
- (계획) 다음과 같은 시나리오를 구상해 보세요. “특정 정당에 대한 지지 여부(이진 변수)는 응답자의 연령대, 성별, 소득 수준, 그리고 최종 학력과 관련이 있다.” 이 데이터의 구조를 설계해 보고, 모든 데이터를 한눈에 보여줄 수 있는 그래프를 스케치해 보세요.
- (시뮬레이션) 위 시나리오를 바탕으로 가상의 데이터를 생성해 보세요. 데이터의 무결성을 검증하기 위해 최소 10개의 테스트 코드를 포함하세요.
- (수집) 이 분석에 필요한 실제 인구 통계 및 설문 자료를 어디서 구할 수 있을지 조사해 보세요.
- (탐색)
ggplot2를 사용하여 직접 스케치한 그래프를 구현해 보고,rstanarm패키지(예:stan_glmer)를 활용해 모델을 추정해 보세요. - (소통) 분석 과정과 주요 결과를 요약한 짧은 보고서(두 단락 내외)를 작성해 보세요.
퀴즈
- MRP(사후 층화 다단계 회귀)가 무엇인지 정의하고, 이 분석 기법에서 사용되는 주요 전문 용어들을 포함하여 강점과 한계를 상세히 설명해 보세요. (최소 세 단락 이상)
- Wang et al. (2015) 의 연구에서 인상 깊었던 점 세 가지와 한계를 꼽아보세요.
- Wang et al. (2015) 의 연구에서 나타난 MRP의 현실적인 약점은 무엇이었나요? (하나 선택)
- 방대한 데이터 요구 사항
- 의도적으로 편향된 데이터 수집 허용
- 분석 수행 및 데이터 확보 비용의 과다
- Wang et al. (2015) 의 연구에 쓰인 ’Xbox 사용자 표본’에 대해 가장 우려되는 지점은 무엇인가요? (하나 선택)
- 전체 유권자를 대표하지 못하는 비대표성(Selection bias)
- 너무 적은 전체 응답자 수
- 동일 응답자가 여러 번 설문에 참여할 가능성
- 차기 대선에서 소득 수준이 투표 의향에 미치는 영향을 로지스틱 회귀 모델로 연구하고자 합니다. 이때 활용 가능한 모델의 입력 변수(Features)는 무엇일까요? (해당하는 것을 모두 고르세요)
- 응답자의 유권자 등록 여부 (예/아니오)
- 응답자의 특정 후보 지지 여부 (예/아니오)
- 응답자의 인종 (범주형 변수)
- 응답자의 혼인 상태 (기혼/미혼)
- Cohn (2016) 의 기사를 읽고 토론해 보세요. 분석 그룹의 가정이 다르면 왜 결과가 판이하게 달라질 수 있는지 논의해 보세요.
- 설문 데이터를 훈련 데이터로 쓰고, ACS 데이터셋을 사후 층화에 활용할 때 실무적으로 가장 빈번하게 발생하는 문제와 고려 사항은 무엇인가요?
- 설문 데이터의 연령 범주는 ’18-29, 30-44, 45-60, 60+’이고, 사후 층화 데이터는 ’18-34, 35-49, 50-64, 65+’로 서로 다릅니다. 이 두 데이터셋을 어떻게 하나로 통합하여 분석할 수 있을까요? 본인만의 전략을 서술해 보세요.
수업 활동
- 논문 비평: Wang et al. (2015) 등의 논문을 정독하고, 편향된 표본이 가지는 데이터 과학적 가치에 대해 비판적으로 토론해 보세요.
과제
당신이 민간 분석 회사에서 미국 유권자 데이터베이스에 접근할 수 있게 되었다고 가정해 봅시다(Ghitza and Gelman (2020) 의 연구와 유사한 상황). 2020년 미국 협동 선거 연구(CES) 자료로 모델을 훈련하고 사후 층화를 수행하는 프로젝트를 진행합니다.
- 데이터시트 작성: Gebru et al. (2021) 의 가이드라인에 따라 해당 유권자 파일에 대한 데이터시트를 작성해 보세요.
- 모델 카드 생성: Mitchell et al. (2019) 의 양식을 활용해 분석에 쓰인 모델에 대한 모델 카드를 작성해 보세요.
- 윤리적 토론: 모델에 사용된 개인 정보 및 기능(Features)과 관련하여 발생할 수 있는 윤리적 쟁점 세 가지를 선정하여 각 쟁점당 두 단락 내외로 논의해 보세요.
- 테스트 계획: 분석의 신뢰성을 확보하기 위해 데이터셋, 모델링 과정, 그리고 예측 결과물에 대해 각각 어떤 검증 테스트를 적용할지 구체적으로 계획해 보세요.
논문
이 시점에서 온라인 부록 F의 Spofforth 논문이 적절할 것입니다.