1 10.4.3 Categorical Risk Factor
Risk factor 가 3 개 이상 카테고리 (예: 사회 계층 6 단계, 음주 4 단계). Dummy coding 으로 logistic 에 입력 (Woodward, 2014, Ch.10.4.3).
Reference category 선정: 한 카테고리를 baseline 으로 — 나머지 OR 가 baseline 대비.
\(k\) 카테고리 → \(k-1\) dummy 변수.
1.1 Dummy Coding 예시 — H. pylori (Table 10.3)
사회 계층 6 단계 (I, II, IIIn, IIIm, IV, V).
Reference = I (전문직 비-수공): - \(D_2 = 1\) if II, else 0. - \(D_3 = 1\) if IIIn, else 0. - \(D_4 = 1\) if IIIm, else 0. - \(D_5 = 1\) if IV, else 0. - \(D_6 = 1\) if V, else 0.
Logistic: \[\text{logit}(r) = b_0 + b_2 D_2 + b_3 D_3 + b_4 D_4 + b_5 D_5 + b_6 D_6\]
각 \(\exp(b_j)\) = 카테고리 \(j\) 의 OR vs reference (I).
- 추상: \(k-1\) 변수가 \(k\) 카테고리의 효과를 reference 대비 \(k-1\) contrast 로 표현.
- 일상어 비유: 6 학년 학생들의 성적 비교 — 1 학년이 baseline, 2~6 학년 각각의 차이.
- 반사실: Reference 가 6 으로 바뀌면 OR 모두 역수 — 부호 반대. 단 모형 적합 결과 (likelihood, predicted prob) 동일.
1.2 Reference Category 선택의 영향
Reference 카테고리는 임의 선택 — OR 의 절대값은 같지만 어느 방향으로 보고할지 결정.
선택 기준: - 임상 표준: 정상 또는 가장 흔한 카테고리. - 표본 크기: 가장 큰 카테고리 (CI 가장 좁음). - 흥미: 비교 흥미 있는 카테고리.
3 단계 직관:
- 추상: \(\beta_j\) 가 reference 의 함수. Reference 변경 = 파라미터화 변경.
- 일상어 비유: 학년 평균 점수 비교에서 1 학년 vs 6 학년 — 1 학년 baseline 이면 +20 점, 6 학년 baseline 이면 -20 점.
- 반사실: Reference 변경 후 결과 동일 (적합도, 예측). 단 보고 readability 만 다름.
2 10.4.4 Ordinal Variable — Trend Test
옵션 1 — Categorical (dummy): 카테고리 dummy 사용. 순서 정보 폐기. 옵션 2 — Linear (trend): 카테고리 1, 2, 3, … 으로 연속 변수처럼. 단조 증가/감소 가정.
Trend test: 옵션 2 로 적합 후 \(H_0: \beta_1 = 0\) 검정.
2.1 Trend Test 의 함정
Trend test 는 카테고리 간격이 동등 (1, 2, 3, …) 이라는 가정. 실제 사회 계층 1~6 의 “거리” 가 동등하지 않을 수 있음.
3 단계 직관:
- 추상: 코드 (1, 2, 3, 4, 5, 6) 가 진성 위험 인자 의미와 부합해야 trend 의 해석이 정직.
- 일상어 비유: 등급 A, B, C, D, F 의 차이가 일정 점수 간격이 아님. 단순 1~5 코드는 부정확.
- 반사실: 카테고리별 OR 패턴 시각화 후 단조 증가/감소 확인 → trend 적합 정당화.
2.2 결합 — Categorical + Linear Trend
베스트 프랙티스 — 두 모형 모두 적합:
- Categorical: 카테고리별 OR 추정 + 시각화.
- Linear: trend test 의 p-value.
두 결과가 일치 (단조 패턴 + 유의 trend) 면 결과 신뢰성 ↑.
3 10.4.5 Floating Absolute Risks (FAR)
Reference category 선택의 자의성을 우회하는 도구.
각 카테고리의 OR 의 분산을 reference 와의 covariance 까지 고려해 산출 → reference 자체의 OR ≠ 1 로 표시 가능.
(Plummer, 2004; Easton et al., 1991).
3.1 Reference 의 분산 = 0 함정
표준 logistic 의 dummy coding 에서 reference 의 OR 는 정확히 1, CI 는 [1, 1] — 분산 0 으로 표시.
진성: Reference 의 진성 OR 는 표본의 결과 — noise 있음. 분산 0 은 인위적 0.
3 단계 직관:
- 추상: Reference 의 OR 분산을 0 으로 두면 다른 카테고리와의 비교 시 분산이 reference 의 무한 정밀도 가정.
- 일상어 비유: 학년 평균 점수 비교 — 1 학년 평균을 정확히 80 점으로 가정하면, 다른 학년 비교의 노이즈가 1 학년 noise 무시.
- 반사실: Reference 의 noise 도 OR 비교에 반영해야 — FAR 가 이를 보정.
3.2 FAR 의 산출
Plummer (2004) 의 floating variance 산출:
\[\text{Var}(\log\hat r_j^*) = \text{Var}(\log\hat r_j) - \text{Var}(\log\hat r_0^*)\]
여기서 \(\log\hat r_0^*\) 는 reference 의 floating log risk.
각 카테고리의 floating CI = reference 의 noise 까지 반영.
FAR plot 에서 모든 카테고리가 noise 있는 점으로 표시 — reference 도 정확한 1 이 아닌 noise 점.
- 추상: 모든 카테고리의 분산이 동등 처리 → 비교 정직.
- 일상어 비유: 학년 평균을 모두 noise 있는 추정으로 표시 → 1 학년만 정확하다는 잘못된 인상 회피.
- 반사실: 표준 dummy plot 은 reference 의 절대 정확도 가정 → FAR 가 이를 보정.
3.3 한계
FAR 는 Cox 모형의 복잡 사례 (예: meta-analysis) 에서 주로 활용. 일반 logistic 에서는 표준 dummy + Wald CI 가 충분한 경우 다수.
4 코드 예시 — Categorical + Trend Test
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.formula.api import logit
np.random.seed(42)
n = 600
# 가상 자료: 사회 계층 6 단계 + H. pylori 감염
sclass = np.random.choice(["I", "II", "IIIn", "IIIm", "IV", "V"], n)
sclass_num = pd.Series(sclass).map({"I": 1, "II": 2, "IIIn": 3, "IIIm": 4, "IV": 5, "V": 6})
# 진성: 계층 ↑ 따라 log OR 0.4 증가
log_odds = -2.0 + 0.4 * sclass_num
prob = 1 / (1 + np.exp(-log_odds))
infected = np.random.binomial(1, prob, n)
df = pd.DataFrame({"sclass": sclass, "sclass_num": sclass_num, "infected": infected})
# 1. Categorical (dummy)
m_cat = logit("infected ~ C(sclass, Treatment(reference='I'))", data=df).fit(disp=0)
print("Categorical OR:")
for term in m_cat.params.index:
if term != "Intercept":
OR = np.exp(m_cat.params[term])
print(f" {term}: OR = {OR:.2f}")
# 2. Linear (trend)
m_lin = logit("infected ~ sclass_num", data=df).fit(disp=0)
OR_unit = np.exp(m_lin.params["sclass_num"])
print(f"\nTrend per category: OR = {OR_unit:.2f} per step")
print(f"Trend p-value: {m_lin.pvalues['sclass_num']:.4f}")
# 3. LR test (categorical vs linear)
m_null = logit("infected ~ 1", data=df).fit(disp=0)
LR_cat = 2 * (m_cat.llf - m_null.llf)
LR_lin = 2 * (m_lin.llf - m_null.llf)
print(f"\nLR (categorical vs null): {LR_cat:.2f} (df=5)")
print(f"LR (linear vs null): {LR_lin:.2f} (df=1)")
print(f"LR (categorical vs linear): {2*(m_cat.llf - m_lin.llf):.2f} (df=4) — non-linearity 검정")해석: 두 모형의 LR 비교가 비선형성 검정 — 차이가 작으면 linear (trend) 충분, 크면 categorical 또는 비선형 변환 필요.
5 A/B 테스트의 categorical 변수
A/B 테스트의 사전 변수 (사용자 segment, 채널, 디바이스) 는 흔히 범주형.
| 변수 | 카테고리 |
|---|---|
| 가입 채널 | Organic / Paid / Referral |
| 디바이스 | iOS / Android / Web |
| Segment | Heavy / Medium / Light |
- 추상: Treatment × Categorical 상호작용 → 각 카테고리의 lift 추정.
- 일상어 비유: 신약 효과를 연령대별로 따로 추정 — 어느 연령군에 효과 ↑ 식별.
- 반사실: 단순 평균 lift 만 보면 segment 별 효과 가림. Categorical interaction 이 HTE 의 첫 단계.
6 Coding Schemes — Dummy 의 대안
1. Dummy (Treatment) coding: - Reference 1 개, 나머지 dummy. - \(\beta_j\) = reference 대비 차이.
2. Effect (Sum) coding: - 모든 카테고리의 평균이 reference. - \(\beta_j\) = grand mean 대비 차이.
3. Helmert coding: - 각 카테고리 vs 이전 카테고리의 평균. - 순서가 의미 있을 때.
4. Polynomial coding: - Linear, quadratic, cubic 추세. - 순서형 변수의 추세 검정.
- 추상 정의: 다른 coding = 다른 contrast. 같은 자료, 다른 해석.
- 일상어 비유: 시험 점수 비교 — 1 등 기준 (dummy), 평균 기준 (effect), 직전 등 기준 (Helmert).
- 반사실 시나리오: Dummy 가 표준 임상, polynomial 이 dose-response 자연.
7 Generalized Logits — Multinomial Outcome
이항 결과 → 다항 결과 (3+ 카테고리) 일반화.
\[\log\left(\frac{P(Y = j)}{P(Y = K)}\right) = \beta_{0j} + \beta_j^T X, \quad j = 1, \ldots, K-1\]
\(K\) = reference 카테고리.
예시: 처치 결과 = “악화 / 변화 없음 / 호전” (3 카테고리).
- 추상 정의: \(K-1\) 개의 logit (각 vs reference). 모든 카테고리 비교.
- 일상어 비유: 여러 후보 중 1 명 선택 — 각 후보의 logit.
- 반사실 시나리오: Ordinal 자료 (예: 악화 → 호전 의 순서) 에 multinomial 적용 시 순서 정보 폐기. Ordinal logistic 우월.
8 Proportional Odds Model — Ordinal Logistic
순서형 outcome (\(Y \in \{1, 2, \ldots, K\}\)) 의 logistic:
\[\log\left(\frac{P(Y \le j)}{P(Y > j)}\right) = \alpha_j - \beta^T X\]
각 cumulative logit (≤ j vs > j) 의 모형. PO 가정: 모든 \(j\) 의 \(\beta\) 동일.
Brant test: PO 가정의 통계 검정.
3 단계 직관:
- 추상 정의: \(\beta(j) = \beta\) 모든 \(j\) — 강한 가정.
- 일상어 비유: 각 cumulative cut-point 의 효과 비 일정.
- 반사실 시나리오: PO 위반 시 partial PO 또는 multinomial. 단 PO 가 일반적 합리적 근사.
9 사례 — 다양한 Categorical 처리
| 사회 계층 | OR (vs I) |
|---|---|
| I (전문직) | 1.0 (ref) |
| II | 2.6 |
| IIIn | 4.6 |
| IIIm | 8.4 |
| IV | 9.5 |
| V | 12.4 |
Linear trend: OR 1.65 per step. LR test (categorical vs linear): p < 0.001 → trend 부적합 (early ↑ 후 plateau).
3 단계 직관:
- 추상 정의: 자료가 비-단조 또는 비-동등 간격 → categorical 우선.
- 일상어 비유: 학년 1~6 의 점수 비교 — 동등 간격 가정 위반.
- 반사실 시나리오: Trend 만 사용 시 진성 패턴 가림. Categorical + trend 모두 보고.
| BMI | OR (vs 정상) |
|---|---|
| < 25 (정상) | 1.0 |
| 25~30 (과체중) | 1.5 |
| 30~35 (비만) | 2.5 |
| > 35 (고도비만) | 4.0 |
활용: 임상 임계값 (WHO 기준) 사용 — 임상 표준.
3 단계 직관:
- 추상 정의: 임상 임계값이 categorical 의 자연 cut-point.
- 일상어 비유: 시험 등급 (A, B, C, D, F) 의 표준 cut-point.
- 반사실 시나리오: 자료 기반 cut-point 시 cherry-picking 위험. 임상 임계값이 정직.
10 A/B 테스트의 Categorical 활용
# A/B + 사용자 segment interaction
import statsmodels.formula.api as smf
m = smf.logit(
"conversion ~ treatment * C(user_segment)",
data=df
).fit()
# 각 segment 의 lift
for seg in df["user_segment"].unique():
OR = np.exp(m.params[f"treatment:C(user_segment)[T.{seg}]"])
print(f"{seg}: OR = {OR:.3f}")3 단계 직관:
- 추상 정의: Categorical interaction 으로 segment 별 lift 추정.
- 일상어 비유: 광고 효과의 시장별 분석.
- 반사실 시나리오: 평균 lift 만 보면 segment 별 차이 가림. Categorical interaction 이 personalization 시작.
11 결론
Categorical 변수는 dummy coding + reference category 선정. Ordinal 은 trend + categorical 두 모형 비교. FAR 는 reference 의 자의성 우회 도구. Multinomial 과 PO 가 다항·순서 outcome 일반화. 임상 임계값이 categorical 의 표준 cut-point. 다음 글 (H-WOO10-4) 에서 다중 logistic 의 일반 구조를 본다.
12 관련 주제
Statistics 크로스링크