변수 6 범주 분류 — 각 카테고리의 인과 역할과 시점 결정 (Buisson Ch.4.2)

Personality Traits, Demographics, Business Rules, Time Trends — 각 변수의 역할 깊이 분석

Buisson (2021) Ch.4 의 variable identification 절을 자세히 정리한다. Personal characteristics 의 traits vs demographics 분리, Business behaviors 가 비즈니스 룰을 어떻게 표현하는가, Time trends 의 추세·주기·일회성 이벤트 — 각 카테고리에서 변수의 CD 내 역할 (confounder, mediator, proxy) 과 시점을 어떻게 결정하는지 호텔 사례로 분석한다.

Experimentation
Causal Inference
저자

Kwangmin Kim

공개

2026년 05월 08일

1 정의

정의: 변수의 역할 분류

CD 에 변수를 추가할 때 분석가가 결정해야 할 두 가지 (Buisson, 2021, Ch.4):

  1. 인과 역할 (causal role):
    • Confounder (공통 원인) — Treatment 와 Outcome 양쪽으로 화살표
    • Mediator (매개) — Treatment 의 영향을 Outcome 으로 전달
    • Effect Modifier (효과 수정) — Treatment 효과의 크기를 변경
    • Direct Cause of Outcome only — Outcome 에만 화살표 (Treatment 무관)
  2. 시점 (temporal precedence): Treatment 결정 전·후 인지

이 두 결정으로 변수의 CD 내 위치와 회귀 처리 방식이 정해진다.

직관 — 같은 변수가 다른 분석에서 다른 역할

PreviousCancellation 이라는 변수가:

  • 호텔의 NRD 정책 분석에서 → Confounder (NRD 와 Cancel 양쪽 영향)
  • 고객 충성도 분석에서 → Outcome (충성 고객이 안 취소함)
  • 가격 인상 효과 분석에서 → Effect Modifier (과거 취소자가 가격 인상에 더 민감)

→ 변수의 본질은 분석 질문에 따라 바뀜. 변수마다 “고정 역할” 이 있는 게 아님.

분석 질문이 결정되어야 변수의 역할이 정해짐. 이게 Starter CD 가 분석의 출발점인 이유.

2 Personal Characteristics — Traits 와 Demographics 의 분리

2.1 Demographics 의 함정

데이터에 있는 demographic 변수의 위험

분석가의 자연스러운 직감: “Age, Gender, Country 같은 demographic 변수를 넣자.”

함정:

  • Demographic 변수 자체는 미관측 personal trait (성격, 가치관, 습관) 의 proxy 일 뿐
  • Demographic 만 넣으면 진짜 인과 변수의 부분 통제만 됨
  • 분석가가 “demographic 통제했음” 이라고 착각하지만 잔여 confounding 큼
직관 — Trait 부터 생각

Buisson 의 권장: Trait 부터 brainstorm, 그 다음 그 trait 의 proxy 인 demographic 을 매핑.

호텔 사례:

[Personality Trait]              [Demographic proxy]
- Conscientiousness (성실성)  ←  Age, IsRepeatedGuest
- Neuroticism (신경증)        ←  (proxy 어려움)
- Risk Tolerance              ←  CustomerType, ADR
- Time Pressure               ←  TripReason, Quarter

이 순서가 분석가의 사고를 깊게 만든다. 단순히 “Age 가 confounder 일 것” 보다, “성실한 사람이 NRD 를 더 많이 받고 덜 취소할 것이다 → 성실성의 proxy 로 IsRepeatedGuest 사용” 이 더 정확.

2.2 호텔 사례의 Trait 후보

Big Five 성격 차원 활용

심리학의 Big Five (OCEAN):

  • Openness (개방성)
  • Conscientiousness (성실성)
  • Extraversion (외향성)
  • Agreeableness (친화성)
  • Neuroticism (신경증)

호텔 취소 분석에 관련된 trait:

Trait NRD 부과 Cancel 가능성 가설
Conscientiousness ↑ 성실한 사람은 약속을 지킴 → 호텔이 NRD 면제, 본인도 안 취소
Neuroticism ↑ (관계 없음) 불안한 사람은 일정 변경 자주 → 취소율 ↑
Risk Tolerance ↑ (관계 없음) 위험 감수형은 NRD 를 sunk cost 로 받아들이고 가서 묵음
Openness ↑ (관계 없음) 새 경험 추구 → 다른 호텔로 옮길 가능성
직관 — 이 trait 들이 모두 미관측

이 trait 들은 호텔 데이터에 없음. 그러나 CD 에 그려둠:

[Conscientiousness]      [Neuroticism]
       ↓        ↓                ↓
   NRDeposit ──→ IsCanceled

(미관측은 음영 또는 대괄호 [ ] 로 표기)

미관측을 그리는 이유:

  • 분석가가 잔여 confounding 을 인식
  • 보고서에 명시 (“이 미관측 변수는 통제 안 됨”)
  • 추후 데이터 수집 우선순위 (성격 검사 추가?)
  • Proxy 식별 (어떤 관측 변수가 이 trait 를 부분 노출?)

2.3 Demographic 변수의 Proxy 역할

호텔 데이터의 proxy 매핑
Trait (미관측) Demographic Proxy (관측) 강도
Conscientiousness IsRepeatedGuest, PreviousCancellation 중간
Risk Tolerance ADR (가격 수용도), CustomerType (Group vs Individual) 약함
Time Pressure TripReason ↔︎ MarketSegment 중간
가족 책임감 Children 강함 (가족 동반 = 책임감)
Income / 가격 민감도 ADR, Country 중간

→ Demographic 을 회귀에 포함하면 trait 의 부분 통제. 완벽 안 함.

Buisson 의 표현: “Financial characteristics” 라는 묶음 (CustomerType + MarketSegment + DistributionChannel + Children + ADR + Country) 으로 통합 가능.

직관 — Aggregation 의 한계

Demographic 을 한 묶음 (“Financial Characteristics”) 으로 aggregate 하면 CD 단순화. 그러나:

  • 회귀에서는 분리해서 사용 (각 변수의 효과 추정)
  • 한 묶음으로 합치면 정보 손실

→ CD 는 통합으로 가독성, 회귀는 분리로 정밀도. 두 표현을 함께 사용. (E-BUI3-2 의 Aggregating Variables 참조.)

2.4 호텔 사례의 갱신된 CD

Personal Characteristics 단계 후의 CD
[TripReason]    [CancellationReason]   [UnderstandsNRD]   [TreatsNRDasSunkCost]
[Conscientiousness] [Neuroticism]
       ↓                        ↓                                        ↓
       │                        │                                        │
       ↓                        ↓                                        ↓
   ┌──────────────────────────────────────────────────────────────────────┐
   │                                                                      │
   │  PreviousCancellation, IsRepeatedGuest                              │
   │  CustomerType, MarketSegment, DistributionChannel                   │
   │  Children, ADR, Country                                              │
   │            ↓                                                         │
   │     Financial Characteristics (묶음)                                 │
   │            ↓                                                         │
   │       NRDeposit ──→ IsCanceled                                       │
   │                  ↗                                                   │
   └──────────────────────────────────────────────────────────────────────┘

이 CD 가 단계 1 (후보 식별) 의 중간 산출물.

3 Business Behaviors — 비즈니스 룰의 표현

3.1 Business Rules 의 인과적 의미

정의

Business Rule: 회사가 정한 결정 규칙. 일반적으로 변수 → 변수 형태.

호텔 예시:

  • “Country 가 X 면 NRD 부과” — Country → NRD 직접 화살표
  • “Christmas 휴가철 예약은 NRD 부과” — ChristmasHolidays → NRD
  • “PreviousCancellation = 1 이면 NRD 부과” — PrevCancel → NRD

이 룰들은 결정론적 화살표. 통계적 연관이 아닌 규칙에 의한 강제.

직관 — Business Rule 이 CD 에 미치는 영향

분석가의 흔한 실수: “PreviousCancellation 의 NRD 효과를 통계로 추정.” → 의미 없음. 이게 회사 정책이면 추정 결과는 정책의 100% 반영일 뿐, 인과 효과 추정 아님.

대신 권장:

  1. 비즈니스 파트너에게 모든 NRD 부과 룰 인터뷰
  2. 룰에 명시된 변수는 NRD 의 결정론적 원인 으로 표기 (인과 효과 추정 불필요)
  3. 룰 외 변수들의 NRD 효과를 통계로 추정

→ Business Rule 인터뷰가 분석의 시간 절약. 안 해보면 통계로 룰을 재발견하느라 시간 낭비.

3.2 Business Rule 의 두 표현 방식

1. 직접 화살표

룰: “PreviousCancellation = 1 이면 NRD = 1”

PreviousCancellation ──→ NRDeposit

직접 화살표. 다른 변수의 영향 없이 단일 룰.

2. 매개 변수 (Mediator)

룰: “Christmas 휴가 예약 (Q4 + 어린이 동반 + 7일 이상) 은 NRD 부과”

여러 변수의 조합. CD 표현:

Quarter, Children, StayLength
              ↓
       ChristmasHolidayFlag (생성된 매개 변수)
              ↓
           NRDeposit

새 변수 ChristmasHolidayFlag 를 생성. 데이터에 없어도 룰에서 도출 가능.

직관 — 매개 변수 생성의 가치

데이터에는 Quarter, Children 같은 raw 변수만 있을 수 있다. 그러나 비즈니스 룰을 알면:

  • Raw 변수의 조합이 의미 있는 단위 (ChristmasHoliday) 로 묶임
  • 회귀에 raw 변수 대신 묶음 변수 사용 → 모형 단순
  • 비즈니스 의사결정 (예: “휴가철 NRD 정책 변경”) 에 직접 매핑

→ Feature Engineering 의 인과추론 버전. 도메인 지식이 변수 생성을 가이드.

3.3 Business Rule 이 미관측 변수를 노출

직관 — 룰 안에 있는 변수는 반드시 측정 가능

“어떤 기준이 비즈니스 룰의 일부면, 그 기준은 정의상 관측 가능하다 (그렇지 않으면 룰을 어떻게 적용하겠는가).”

— Buisson

따라서:

  • 룰 인터뷰가 숨겨진 관측 변수 를 노출시킴
  • 데이터베이스에 컬럼이 없어도, 직원의 결정 절차에 있으면 캐낼 수 있음
  • 분석가의 데이터 보강 우선순위 결정

호텔 사례: “직원이 신용카드 한도를 보고 NRD 부과 결정” → 카드 한도 데이터를 DB 에 추가하면 강력한 confounder 통제 가능.

5 검증 절차 — 단계 2 의 통계 도구

5.1 수치 변수 — Pearson 상관

단순 상관 행렬

후보 변수 중 수치형 (또는 binary 0/1) 변수만 추려 상관 행렬:

numeric_vars = ["NRDeposit", "IsCanceled", "Children", "ADR",
                "PrevCancel", "RepGuest", "Year"]
corr_matrix = df[numeric_vars].corr()

판단 임계값: Treatment 와 Outcome 의 상관 계수 (예: 0.16) 와 같은 자릿수의 상관을 가진 변수는 회귀에 포함 후보.

직관 — “같은 자릿수” 임계값

Buisson 의 휴리스틱:

“Treatment ↔︎ Outcome 의 상관이 0.16 이면, 어떤 변수가 그것들과 0.1 이상 상관을 가지면 포함.”

이 임계값이 상대적. Treatment-Outcome 상관이 큰 분석에서는 임계값도 큼, 작은 분석에서는 작음.

이유: 작은 상관 (0.05 정도) 의 변수가 많으면 중요한 변수의 효과가 가려짐. 큰 상관과 같은 자릿수만 포함하면 분석이 깔끔.

비과학적 임계값임. 변수가 적으면 0.05 도 포함, 많으면 0.2 이상만 포함.

직관 — 상관이 작아도 confounder 가능

이론적: A가 confounder 라도 marginal 상관이 작을 수 있음. 다른 변수와 결합 시 강한 영향.

따라서: 상관 행렬은 첫 필터. 강한 도메인 직관이 있으면 작은 상관의 변수도 포함.

→ 통계 + 직관의 조합. 통계만으로 결정 안 함.

5.2 범주 변수 — Cramer’s V

정의

수치 변수의 Pearson 상관에 대응하는 범주 변수의 연관 척도.

\[ V = \sqrt{\frac{\chi^2}{n \cdot \min(r-1, k-1)}} \]

  • \(\chi^2\): 카이 제곱 통계량 (분할표에서)
  • \(n\): 표본 크기
  • \(r, k\): 분할표의 행·열 수

해석: \(V \in [0, 1]\). 0 = 독립, 1 = 완전 연관.

직관 — Cramer’s V 의 비즈니스 임계값
V 강도 회귀 포함?
0 ~ 0.1 약함 보통 제외
0.1 ~ 0.3 중간 도메인 직관 따라 결정
0.3+ 강함 거의 확실히 포함

호텔 사례 (Buisson 데이터):

  • NRDeposit ↔︎ IsCanceled: 0.165 (중간) — 분석 대상
  • CustomerType ↔︎ MarketSegment: > 0.5 (강함) — 다중공선성 위험
  • Quarter ↔︎ 다른 변수: 모두 < 0.1 — 제거 후보 (계절성 부재)

5.3 다중공선성 — VIF

정의

VIF (Variance Inflation Factor): 한 변수가 다른 변수들로부터 얼마나 예측 가능한지의 척도.

\[ \text{VIF}_j = \frac{1}{1 - R_j^2} \]

여기서 \(R_j^2\) 는 변수 \(j\) 를 다른 모든 변수로 회귀한 결정계수.

해석:

  • VIF = 1: 다른 변수와 무관
  • VIF = 5: 다른 변수의 5 배 잡음으로 추정
  • VIF > 10: 심각한 다중공선성 — 변수 선별 필요
직관 — 다중공선성이 분석을 망가뜨리는 방식

CustomerType, MarketSegment, DistributionChannel 이 강하게 상관 (Cramer’s V > 0.5):

회귀 결과:

  • 세 변수 모두 포함 → 각 계수 추정의 표준오차 폭증, 신뢰구간 매우 넓음
  • “어느 변수가 진짜 confounder 인지 결정 불가”

해결:

  1. 선별: 하나만 포함 (가장 의미 있는 것)
  2. 합성: 새 변수 생성 (예: PCA 의 첫 주성분)
  3. 계층화: 한 변수로 stratify, 다른 변수는 stratum 내 회귀

→ 다중공선성을 무시하면 분석이 통계적으로는 돌아가지만 결과가 무의미.

5.4 검증 후 갱신된 CD

호텔 사례 — 단계 2 후
Customer Type, IsRepeatedGuest, Year
       ↓                ↓                  ↓
   ┌────────────────────────────────────┐
   │                                      │
   │  Children         PrevCancel         │
   │     ↓                ↓                │
   │  Market Segment   ADR                 │
   │  Distribution Ch  Country             │
   │     ↓                ↓                │
   │     └→ NRDeposit ──→ IsCanceled       │
   │                                      │
   │  (Quarter 제거 — 작은 V 로 인해)      │
   └────────────────────────────────────┘

검증 결과:

  • 포함: PreviousCancellation, ADR, Children, IsRepeatedGuest, Year (Pearson > 0.1 또는 Cramer’s V > 0.1)
  • 제거: Quarter (모든 변수와 V < 0.1, 계절성 영향 없음)
  • 선별 필요: CustomerType, MarketSegment, DistributionChannel 중 하나 (다중공선성)

6 응용 — 다른 비즈니스 사례의 6 카테고리

6.1 SaaS 사례 — Onboarding 효과

변수 분류

분석 질문: “Onboarding 튜토리얼이 30일 retention 을 높이는가?”

카테고리 후보 변수 역할 가설
Past Actions 이전 SaaS 사용 횟수 Confounder (경험자가 튜토리얼 완료 ↑, retention ↑)
Intentions 사용 목적 (장기 vs 단기) Confounder (장기 사용자가 튜토리얼 완료 + retention ↑)
Cognition 기술 자신감 Mediator (튜토리얼 → 자신감 → retention)
Personal 직무 (Engineer vs Marketing) Confounder (Engineer 가 튜토리얼 완료 ↑)
Business 가입 경로 (광고 vs 추천) Confounder (추천이 의도 ↑)
Time Trends 가입 코호트 (월별) Confounder (시기별 사용자 다름)

6.2 이커머스 사례 — 추천 효과

변수 분류

분석 질문: “추천이 구매 전환을 높이는가?”

카테고리 후보 변수 역할 가설
Past Actions 과거 구매 빈도 Confounder (자주 사는 사람이 추천도 더 받고 더 사고)
Intentions 검색 의도 (browsing vs buy) Confounder (의도 강할수록 추천도 받고 사고)
Cognition 가격 비교 인지 Effect Modifier (가격 비교한 사람은 추천 효과 ↓)
Personal 인구통계 Confounder (proxy for 선호)
Business 디바이스, 시간대 Confounder (모바일 / 데스크톱 다름)
Time Trends 계절 (Black Friday) Confounder + Effect Modifier

7 코드 예시 — Python 으로 변수 검증

7.1 Pearson 상관 + Cramer’s V 통합

import numpy as np
import pandas as pd
from scipy.stats import chi2_contingency

def cramers_v(x, y):
    """범주 변수의 연관 강도."""
    confusion = pd.crosstab(x, y)
    chi2, _, _, _ = chi2_contingency(confusion)
    n = confusion.values.sum()
    r, k = confusion.shape
    return np.sqrt(chi2 / (n * (min(r, k) - 1)))


def association_matrix(df, target_col):
    """
    target 과 다른 변수들의 연관 점수.
    수치-수치: Pearson, 범주-수치: 점bisearial (Pearson 으로 근사),
    범주-범주: Cramer's V.
    """
    results = []
    for col in df.columns:
        if col == target_col:
            continue
        if pd.api.types.is_numeric_dtype(df[col]) and pd.api.types.is_numeric_dtype(df[target_col]):
            score = df[col].corr(df[target_col])
            method = "Pearson"
        else:
            score = cramers_v(df[col], df[target_col])
            method = "Cramer's V"
        results.append({"variable": col, "score": score, "method": method})

    return pd.DataFrame(results).sort_values("score", key=abs, ascending=False)


# 가상 호텔 데이터
np.random.seed(42)
n = 5000
df_hotel = pd.DataFrame({
    "NRDeposit": np.random.binomial(1, 0.05, n),
    "IsCanceled": np.random.binomial(1, 0.3, n),
    "PrevCancel": np.random.binomial(1, 0.1, n),
    "RepeatedGuest": np.random.binomial(1, 0.2, n),
    "Children": np.random.poisson(0.3, n),
    "ADR": np.random.lognormal(4.5, 0.5, n),
    "CustomerType": np.random.choice(["Transient", "Group", "Contract"], n),
    "MarketSegment": np.random.choice(["Direct", "OnlineTA", "Group"], n),
    "Quarter": np.random.choice([1, 2, 3, 4], n),
})

# 합성된 confounding (PrevCancel 이 두 변수에 영향)
df_hotel["NRDeposit"] = (
    df_hotel["PrevCancel"] * 0.5
    + np.random.binomial(1, 0.05, n)
).clip(0, 1).astype(int)
df_hotel["IsCanceled"] = (
    df_hotel["PrevCancel"] * 0.3
    + np.random.binomial(1, 0.3, n)
).clip(0, 1).astype(int)

# 연관 점수
print("=== NRDeposit 과 다른 변수 연관 ===")
result_nrd = association_matrix(df_hotel, "NRDeposit")
print(result_nrd.to_string(index=False))

print("\n=== IsCanceled 과 다른 변수 연관 ===")
result_cancel = association_matrix(df_hotel, "IsCanceled")
print(result_cancel.to_string(index=False))
직관 — 통합 도구의 가치

이 함수는 수치-수치, 수치-범주, 범주-범주 모두 처리. 분석가가 변수 유형마다 다른 도구를 신경 쓸 필요 없음.

→ 후보 변수 100 개여도 한 번에 점수 매김. 임계값 (V > 0.1) 으로 자동 필터.

이 자동화는 첫 필터 일 뿐. 결과를 본 후 도메인 직관으로 보강.

7.2 VIF 진단

from statsmodels.stats.outliers_influence import variance_inflation_factor

def calculate_vif(df, columns):
    """수치 변수의 VIF 계산."""
    X = df[columns].values
    vif_data = pd.DataFrame()
    vif_data["Variable"] = columns
    vif_data["VIF"] = [
        variance_inflation_factor(X, i) for i in range(len(columns))
    ]
    return vif_data.sort_values("VIF", ascending=False)


# 수치형 변수만 추려 VIF
numeric_cols = ["PrevCancel", "RepeatedGuest", "Children", "ADR"]
vif_result = calculate_vif(df_hotel, numeric_cols)
print("\n=== VIF 진단 ===")
print(vif_result.to_string(index=False))
print("\n해석:")
print("  VIF < 5: OK")
print("  VIF 5~10: 주의")
print("  VIF > 10: 변수 선별 필요")
직관 — VIF 결과의 처방

VIF > 10 인 변수가 있으면:

  1. 가장 VIF 높은 변수 제거 후 재계산
  2. 남은 변수의 VIF 가 모두 < 5 가 되도록 반복
  3. 제거된 변수의 정보가 다른 변수에 흡수됨

호텔 사례에서 CustomerType + MarketSegment 둘 다 포함 시 VIF > 10 예상. 하나 제거 → 분석 안정.

7.3 시간 변수 분해

# 추세 + 주기 + 사건 분해
np.random.seed(42)
T = 60  # 60 개월

base_trend = 50 + 0.5 * np.arange(T)  # 선형 추세
seasonality = 10 * np.sin(2 * np.pi * np.arange(T) / 12)  # 12 개월 주기
covid_dummy = ((np.arange(T) >= 28) & (np.arange(T) < 40)).astype(int)
covid_effect = -30 * covid_dummy  # COVID 충격

reservations = base_trend + seasonality + covid_effect + np.random.normal(0, 5, T)

# 회귀로 분해
df_time = pd.DataFrame({
    "month_idx": np.arange(T),
    "month_in_year": np.arange(T) % 12,
    "covid": covid_dummy,
    "reservations": reservations,
})

import statsmodels.api as sm
X = sm.add_constant(df_time[["month_idx", "covid"]])
# 계절 dummy
month_dummies = pd.get_dummies(df_time["month_in_year"], prefix="m", drop_first=True).astype(int)
X = pd.concat([X, month_dummies], axis=1)
m = sm.OLS(df_time["reservations"], X).fit()
print("\n=== 시간 분해 회귀 ===")
print(f"  추세 (month_idx): {m.params['month_idx']:.3f}")
print(f"  COVID 충격: {m.params['covid']:.2f}")
print(f"  R² = {m.rsquared:.3f}")
직관 — 시간 분해의 비즈니스 가치

추정 결과:

  • 추세: 0.5 (월별 0.5 건 증가) — 시장 성장
  • COVID 충격: -30 (3년치 성장 후퇴)
  • R² > 0.9 (시간만으로 대부분 설명)

→ 분석에서 시간 효과를 분리하면 “진짜 NRD 효과” 만 추출 가능. 시간 통제 안 한 분석은 시간 트렌드를 NRD 효과로 오인.

8 관련 주제

8.1 Ch.4 의 형제 글

8.2 이전 챕터

8.3 후속 챕터

8.5 카테고리 진입점

Subscribe

Enjoy this blog? Get notified of new posts by email: