지난 포스팅에서는 수치, 범주형 데이터별 단변량 분석을 정리했다. 이번 포스팅에서는 단변량을 넘어, x / y 축간의 관계를 확인하는 이변량 분석에 대해 알아보자. 단변량 분석과 동일하게 시각화, 수치화를 활용하지만 이변량 분석은 가설검정 도구를 활용해 수치화를 진행한다. 먼저, 가설검정이란 무엇인지 정리해보자.
가설검정
이변량 분석에서 가설 감정은 두 변수 간의 관계를 분석하는데 중요한 역할을 수행한다. 가설검정은 귀무가설(H0)과 대립가설(H1)을 설정하고, 데이터가 귀무가설을 기각할 만큼 충분한 증거가 있는지를 평가한다.
- 귀무가설 : 연구자가 검증하고자 하는 기존 가정 또는 주장이다. 일반적으로 두 집단 간의 차이가 없다거나, 두 변수 간의 관계가 없다는 가정을 나타낸다.
- 대립가설 : 귀무가설과 반대되는 주장으로, 연구자가 입증하고자 하는 새로운 가정이다. 대립가설이 참인 경우, 귀무가설은 기각된다.
예를 들어, 두 집단의 평균 차이를 비교할 때 다음과 같은 가설을 설정할 수 있다.
- H0 : 두 집단의 평균은 동일하다.
- H1 : 두 집단의 평균은 다르다.
가설검정에서는 먼저 유의수준(α)을 설정한 후, 검정통계량을 계산한다. 검정통계량이 기각역(critical region)에 속하면 귀무가설을 기각하고, 그렇지 않으면 귀무가설을 채택한다.
가설검정 절차

1. 연구 가설 설정
- 연구 문제에 대한 귀무가설(H0)과 대립가설(H1)을 명확히 정의
- 예: H0: 두 집단의 평균은 같다. H1: 두 집단의 평균은 다르다.
2. 유의수준(α) 결정
- 귀무가설을 기각할 최대 오류 확률을 지정, 일반적으로 0.05 또는 0.01을 사용
- 유의수준이 작을수록 귀무가설을 기각하기 어려워짐
3. 검정통계량 계산
- 표본 데이터를 바탕으로 검정통계량을 계산
- 검정통계량의 종류는 가설검정 유형과 데이터 분포에 따라 다름 (t-검정, z-검정, F-검정, 카이제곱 검정 등).
4. 기각역 결정 및 검정통계량 해석
- 유의수준에 따라 기각역(critical region)을 결정
- 기각역 : 귀무가설을 기각해야 하는 검정통계량의 값 범위
- 검정통계량이 기각역에 속하면 귀무가설을 기각하고 대립가설을 채택
- 단, 조사의 성격에 따라 양측검정 혹은 단측검정을 진행하는데, 설정한 유의수준을 기준으로 기각역과 채택역이 나눠지고, 양측검정에서는 기각역이 양쪽으로 분할된다.
5. 결과 해석
- p-value를 계산하여 유의성 여부를 판단한다. 만약 p-value가 유의수준보다 작은 경우, 귀무가설을 기각하고 대립가설을 채택한다.
- p-value는 표본의 수에 영향을 많이 받는다. 예를 들어, 표본의 수가 엄청 많은 경우 비교 집단이 굉장히 유사하거나 아예 다르게 해석될 수 있다.
- 따라서, 효과 크기(effect size)를 고려하여 실제 중요성을 평가해야 한다.
- 효과 크기(effect size) : 가설검정에서 유의한 결과가 나왔을 때, 그 결과의 실제적인 중요성이나 의미 있는 정도를 나타내는 지표
가설검정에서 귀무가설을 기각했다는 것은 두 집단 간에 차이가 있다는 통계적 증거가 있다는 의미이다. 하지만 이 차이가 실제로 중요한지, 얼마나 큰 차이인지는 확인할 수 없다. 효과 크기는 이러한 실제적인 중요성을 수치화한 값이다. 효과 크기가 클수록 두 집단 간 차이나 관계의 크기가 크다는 것을 의미한다.
주요 지표는 다음과 같다.
- Cohen's d : 두 집단 평균 차이의 표준화된 값이다.
- r : 두 변수 간 상관계수의 절대값으로, 0.1은 작은 효과, 0.3은 중간 효과, 0.5 이상은 큰 효과로 해석
- Odds Ratio : 두 집단 간 odds(발생 가능성 비율)의 비율이다. 1보다 크면 정적 관계, 1보다 작으면 부적 관계를 나타낸다.
가설검정에서 유의한 결과가 나왔다면, 효과 크기를 함께 보고하는 것이 일반적이다. 이를 통해 결과의 실제적 중요성을 평가할 수 있다. 단순히 통계적 유의성만 보는 것이 아니라, 효과 크기를 함께 고려하여 연구 결과를 종합적으로 해석하는 것이 중요하다.
가설검정의 오류
| 귀무가설이 참 | 귀무가설이 거짓 | |
| 귀무가설 기각 | 제1종 오류 | 정확한 결정 |
| 귀무가설 채택 | 정확한 결정 | 제2종 오류 |
- 제1종 오류: 귀무가설이 참인데 기각하는 오류
- 제2종 오류: 귀무가설이 거짓인데 기각하지 못하는 오류
가설검정에서는 이러한 오류를 최소화하는 것이 중요하다. 일반적으로 제1종 오류를 줄이기 위해 유의수준(α)을 작게 설정한다. 그러나 유의수준을 너무 작게 하면 제2종 오류(β)가 커지게 된다.
따라서 적절한 유의수준과 검정력을 설정하는 것이 필요합니다. 이를 위해서는 효과 크기와 표본 크기를 고려해야 한다.
- 검정력(statistical power) : 귀무가설이 거짓일 때 이를 기각할 확률
- 효과 크기가 클수록 검정력이 증가하여 제2종 오류(β)가 줄어든다.
- 표본 크기가 클수록 검정력이 증가하여 제2종 오류(β)가 줄어든다.
가설검정에서는 이러한 오류를 최소화하는 동시에, 효과 크기와 표본 크기를 함께 고려하여 결과를 해석해야 한다.
이변량 분석(숫자-숫자)
가설검정에 대해 알아봤으니, 이제 이변량 분석을 어떻게 하면 되는지 알아보자. 먼저, 숫자-숫자간의 관계다. 위에서 언급했듯이, 시각화와 수치화라는 방법은 단변량 분석과 동일하다.
산점도(Scatter Plot)

산점도는 두 숫자형 변수 간의 관계를 시각화하는 가장 기본적인 방법이다. 각 관측값을 x-y 평면 상의 점으로 나타내면 두 변수 간의 패턴을 쉽게 파악할 수 있다. 점들의 패턴을 관찰하면 두 변수간의 관계 유형(선형, 비선형, 관계 없음)과 방향성(정비례, 반비례)을 대략적으로 알 수 있다.
scatterplot 외에도 seaborn 패키지는 다양한 시각화 도구를 제공한다. regplot과 jointplot을 사용하면, 산점도에 추가로 추세선 / 히스토그램을 추가한 그림을 출력할 수 있다. 사용자 정의 함수를 활용해 여러가지 데이터를 살펴보는 것도 좋은 방법이다.
def vis_corr(feature, target, data):
plt.subplot(1,2,1)
sns.scatterplot(x=feature, y=target, data=data)
plt.subplot(1,2,2)
sns.regplot(x=feature, y=target, data=data)
sns.jointplot(x=feature, y=target, data=data)
plt.tight_layout()
plt.show()
result = spst.pearsonr(data[feature], data[target])
print(f'상관계수 : {result[0]}, p-value : {result[1]}')
상관계수(Correlation Coefficient)

위의 그림을 보면 여러 형태의 산점도가 있다. 두 숫자형 변수간의 선형 관계 강도를 수치로 나타낸 것이 상관계수이다. 보통, 피어슨 상관계수(Pearson Correlation)가 가장 널리 사용된다.
- 상관계수는 공분산을 표준화한 값으로, -1부터 1사이의 값을 가진다.
- 공분산 : 두 개의 확률 변수 X와 Y의 선형적인 관계를 나타내는 값으로, 음의 무한대에서 양의 무한대까지의 범위를 가진다.
- 1에 가까울수록 강한 정비례 선형관계, -1에 가까울수록 강한 반비례 선형관계를 의미한다.
- 0에 가까우면 선형관계가 약하거나 없음을 뜻한다.
- 두 변수간의 선형관계 정도를 쉽게 파악할 수 있지만, 비선형 관계에 대해서는 설명력이 약하다.
여기서 유의해야할 점이 있다. 상관관계와 인과관계는 다른 개념이다. 예를 들어, 아이스크림 판매량과 범죄율 간에 높은 상관관계가 있다고 해서, 아이스크림 판매가 범죄를 유발한다고 볼 수는 없다. 이 경우 제3의 변수인 기온이 아이스크림 판매와 범죄율에 모두 영향을 미쳤기 때문이다.
즉, 상관관계는 두 변수 간의 연관성을 보여줄 뿐, 그 관계의 원인과 결과에 대해서는 설명하지 못한다.
수치화 : 상관분석
이제 python으로 직접 상관분석을 실행해보자. 상관분석의 가설은 다음과 같다. 단, 값에 NaN(결측치)가 있으면 계산되지 않으므로, 반드시 notnull()로 제외하고 검정을 수행해야한다.
- 귀무가설 : 상관 관계가 없다.(상관계수가 0이다)
- 대립가설 : 상관 관계가 있다.(상관계수가 0이 아니다)
import scipy.stats as spst
# 피어슨 상관계수 계산
corr = data["total_bill"].corr(data["tip"])
print(f"Total Bill과 Tip 간의 상관계수: {corr}")
# 라이브러리 사용
spst.pearsonr(air['Temp'], air['Ozone'])
# PearsonRResult(statistic=0.6833717861490114, pvalue=2.197769800200284e-22)
튜플의 첫 번쨰 값은 상관계수이고, 두 번쨰 값은 p-value를 뜻한다. 유의수준 0.05 기준, p-value가 유의수준 보다 낮기 때문에 귀무가설이 기각된다. 즉, 데이터에서 Temp와 Ozone은 상관관계가 있다고 해석하면 된다.
이변량 분석(범주-숫자)

범주별 숫자를 비교할 때 사용되는 방식은 범주별 평균 비교이다. Data에서 x축에 범주를 주고, 수치를 Y로 두면된다. Seaborn 라이브러리를 사용하면, 별도의 집계없이 바로 평균을 비교할 수 있다.
sns.barplot(x="Survived", y="Age", data=titanic)
plt.grid()
plt.show()
t-test(두 집단 평균 비교)
t-test는 두 집단의 평균 차이가 통계적으로 유의한지 검정하는 방법이다. 상관분석과 동일하게 결측치가 없어야 분석이 가능하다.
- 귀무가설 : 두 집단간 평균에 차이가 없다.
- 대립가설 : 두 집단간 평균에 차이가 있다.
- t-통계량 : 두 평균의 차이를 표준오차로 나눈 값으로, 두 평균의 차이로 이해해도 된다.
여기서 두 집단의 관계에 따라서도 사용하는 방법이 달라진다.
- 독립 표본 T-검정 : 두 독립된 집단의 평균 차이를 검정한다.
- 대응 표본 T-검정(쌍체비교) : 같은 대상 혹은 두 집단이 대응되어 있을 때(치료 전/후 등) 사용
import numpy as np
from scipy.stats import ttest_ind, ttest_rel
# 독립 두 집단 t-test 예시
group1 = [1, 2, 3, 4, 5]
group2 = [4, 5, 6, 7, 8]
t_stat, p_val = ttest_ind(group1, group2)
print(f"t-statistic: {t_stat}, p-value: {p_val}")
# t-statistic: -3.0, p-value: 0.017071681233782634
# 대응 두 집단 t-test 예시
before = [5, 6, 7, 8, 9]
after = [6, 7, 8, 9, 10]
t_stat, p_val = ttest_rel(before, after)
print(f"t-statistic: {t_stat}, p-value: {p_val}")
# t-statistic: -inf, p-value: 0.0
독립 표본 T-검정의 경우, t 통계량이 -3으로 음수이므로, 두 집단의 평균 차이가 음의 방향임을 의미한다. 보통 t 값이 -2보다 작거나, 2보다 크면 차이가 있다고 본다. p-value 역시 0.05보다 작으므로, 두 집단 간 평균 차이가 통계적으로 유의한 것으로 해석된다.
대응표본 T-검정의 경우 before과 after의 차이값들이 모두 1로 동일하기 때문에 t 값의 절대값이 매우 커져서 -inf라는 결과가 출력됐다. 만약 일반적인 데이터로 진행했음에도 inf 값이 출력된다면 Levene의 등분산 검정을 실시하여 두 집단의 분산이 동일한지 확인해볼 필요가 있다.
위의 예시에는 누락됐지만, T검정을 실시하면 t 통계량, p-value 외에도 자유도(degrees of freedom)도 출력된다. 자유도는 통계 분석에서 특정 확률 분포를 결정하는 데 사용된다. 추정해야 할 모수의 수에 따라 달라지는데, 일반적으로 자유도는 전체 관측치 수에서 추정해야 할 모수의 수를 뺀 값으로 계산된다. 예를 들어, 표본 평균을 계산할 때는 전체 관측치 수(n)에서 1(평균)을 뺀 n-1이 자유도가 된다.
t-검정에서 자유도는 다음과 같이 계산된다.
- 독립표본 t-검정 : n1(첫 번째 집단의 표본 크기) + n2(두 번째 집단의 표본 크기) - 2
- 대응표본 t-검정 : n(대응되는 쌍의 수)-1
t-분포에서 자유도가 클수록 정규분포에 가까워지므로, 표본의 크기가 클수록 t-검정의 정확도와 검정력이 높아진다.
ANOVA(세 집단 이상 평균 비교)
ANOVA는 세 개 이상의 집단 간 평균 차이가 통계적으로 유의한지 검정하는 방법이다. 집단 간 변동과 집단 내 변동을 비교하여 집단 평균이 같다는 귀무가설을 검정한다.
- 귀무가설 : 범주별 평균은 차이가 없다.
- 대립가설 : 범주별 평균은 차이가 있다.
- f-통계량 : 집단 간 분산 / 집단 내 분산
ANOVA 분산 검정도 범주형 변수의 개수에 따라 방법이 달라진다,
- 일원 분산분석(One-way ANOVA): 하나의 범주형 변수에 따른 집단 비교
- 이원 분산분석(Two-way ANOVA): 두 개의 범주형 변수에 따른 집단 비교
import pandas as pd
from scipy.stats import f_oneway
# 예제 데이터
data = pd.DataFrame({"score": [80, 85, 90, 75, 82, 78, 92, 88, 95],
"group": ["A", "A", "A", "B", "B", "B", "C", "C", "C"]})
# One-way ANOVA 예시
groups = data.groupby("group")["score"].apply(list)
f_stat, p_val = f_oneway(*groups)
print(f"F-statistic: {f_stat}, p-value: {p_val}")
# F-statistic: 8.053691275167786, p-value: 0.019991333852813854
f-통계량도 t-통계량처럼 값이 2~3 이상이면 차이가 있다고 판단한다. 예제의 경우 그룹별 성적 평균에 차이가 있다고 볼 수 있다. 단, 분산분석은 전체 평균 대비 각 그룹간 차이가 있는 지만 알려준다. 어느 그룹 간에 차이가 있는지는 알 수 없다. 그래서, 특정 집단간의 차이를 식별하려면 사후분석(post-hoc test)를 사용해 집단 간 차이를 개별적으로 비교해야한다. 예를 들어, A, B, C 세 집단에 대해 ANOVA 결과 유의한 차이가 있다고 하면, Tukey's HSD Test를 통해 A-B, A-C, B-C 각 쌍에 대한 평균 차이 검정을 수행할 수 있다.
import pandas as pd
from scipy.stats import f_oneway
import statsmodels.api as sm
from statsmodels.formula.api import ols
from statsmodels.stats.multicomp import pairwise_tukeyhsd
# 예제 데이터
data = pd.DataFrame({"score": [80, 85, 90, 75, 82, 78, 92, 88, 95],
"group": ["A", "A", "A", "B", "B", "B", "C", "C", "C"]})
# One-way ANOVA
groups = data.groupby("group")["score"].apply(list)
f_stat, p_val = f_oneway(*groups)
print(f"F-statistic: {f_stat}, p-value: {p_val}")
# Tukey's HSD Test
model = ols('score ~ C(group)', data=data).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
tukey = pairwise_tukeyhsd(endog=data['score'],
groups=data['group'],
alpha=0.05)
print(tukey)

먼저, ANOVA 결과를 보면 f-통계량 8, p-value 0.019로 세 집단 간 유의한 차이가 있음을 확인할 수 있다. Tukey's HSD Test 결과에서는 각 집단 쌍에 대한 평균 차이(meandiff), 조정된 p-value(p-adj), 신뢰구간(lower, upper)를 보여준다.
- A-B 집단 쌍: 평균 차이 6.6667, 유의하지 않음(p-adj > 0.05)
- A-C 집단 쌍: 평균 차이 -5.6667, 유의하지 않음(p-adj > 0.05)
- B-C 집단 쌍: 평균 차이 -12.3333, 유의함(p-adj < 0.05)
따라서 B집단과 C집단 간에는 유의한 평균 차이가 있지만, A 집단과 B 집단, A 집단과 C 집단 간에는 유의한 차이가 없음을 알 수 있다.
이변량 분석(범주-범주)
범주와 범주간의 관계를 비교 분석하기 위해서는 먼저 교차표를 만들어야한다. 교차표는 pandas의 crosstab(행,열) 메소드를 활용하면 만들 수 있다. 이 때, normalize 옵션으로 수치를 비율로 변환할 수 있다.

# 교차표 제작
pd.crosstab(titanic['Survived'], titanic['Sex'], normalize = 'columns')
시각화
1. 모자이크 그림(Mosaic plot)
모자이크 그림은 두 범주형 변수의 관계를 시각화하는 데 사용되는 그래프로, 각 범주 조합의 빈도를 나타내는 사각형을 나열하여 그린다.

각 사각형은 객실 등급과 생존의 조합을 나타내며, 1등석 탑승객의 생존률이 가장 높고, .3등석 탑승객의 생존 비율이 가장 낮음을 확인할 수 있다.
장점:
- 두 변수 간의 관계를 시각적으로 쉽게 파악 가능
- 각 범주 조합의 빈도를 직관적으로 비교
- 상호작용 효과를 확인하는 데 유용함
단점:
- 범주 수가 많아지면 그림이 복잡해질 수 있음
- 빈도가 낮은 범주 조합은 시각적으로 구분하기 어려움
2. 100% stacked bar
100% stacked bar는 각 범주 내에서 비율을 나타내는 막대 그래프이다. 각 범주 내의 비율을 100%로 표현하여 값을 비교한다.

장점
- 각 범주 내의 비율을 쉽게 비교할 수 있음
- 특정 범주 내에서 다른 범주들의 비율을 파악하는 데 유용함
단점
- 범주 수가 많아지면 그래프가 복잡해질 수 있음
- 전체적인 빈도를 파악하기 어려울 수 있음
카이제곱 검정(Chi-square Test)
카이제곱 검정은 범주형 변수들 사이에 어떤 관계가 있는지 수치화하는 바업ㅂ이다. 두 변수가 서로 독립인지, 변수 간에 연관성이 있는지를 검정한다.
- 귀무가설 : 두 변수는 서로 독립이다.(연관성이 없다.)
- 대립가설 : 두 변수는 서로 독립이 아니다.(관련성이 있다.)
카이제곱 통계량은 관측된 빈도와 기대 빈도 간의 차이를 제곱하여 계산된다. 해당 통계량이 클수록 기대빈도와 실제 값과의 차이가 크다고 해석하면 된다. 단, 분할표를 생성할 때 normalize 옵션을 사용하면 각 셀의 기대 빈도가 행 또는 열의 합계에 비례하도록 조정되기 때문에 원래의 기대 빈도와 차이가 발생한다. 따라서, 카이제곱 검정에서 분할표를 생성할 때는 normalize 옵션을 사용하면 안된다.
import pandas as pd
from scipy.stats import chi2_contingency
# 예제 데이터
data = pd.DataFrame({"성별": ["남", "남", "여", "여", "남", "여"],
"취미": ["운동", "독서", "운동", "음악", "독서", "음악"]})
# 분할표 생성
contingency_table = pd.crosstab(data["성별"], data["취미"])
print(contingency_table)
# 카이제곱 검정
chi2_stat, p_val, dof, expected = chi2_contingency(contingency_table)
print(f"카이제곱 통계량: {chi2_stat:.2f}, p-value: {p_val:.4f}")
카이제곱 통계량: 4.00, p-value: 0.1353
일반적으로, 자유도의 2~3배 보다 카이제곱 통계량이 크면 차이가 있다고 본다. 범주형 변수의 자유도는 범주의 수 - 1 이므로, 여기서는 (2-1) * (3-1) = 2, 2의 2~3배인 4~6 보다 카이제곱 통계량이 크면 차이가 있다고 볼 수 있다. 그런데, p-value의 값이 0.13이다. 만약 p-value의 값만을 본다면 귀무가설을 기각할 충분한 근거가 없기 때문에 두 변수는 서로 독립이 아니라고 해석할 수 있다. 하지만, p-value만으로는 두 변수 간에 관련성이 있는지 확실하게 판단할 수 없다. 분할표의 크기, 모집단의 분포 등 다른 정보들을 고려하여 두 변수 간의 연관성을 판단해야 한다.
자료 출처
'Aivle > Python' 카테고리의 다른 글
| [에이블스쿨] 단변량 분석 (0) | 2024.03.15 |
|---|---|
| [에이블스쿨] Pandas (0) | 2024.03.08 |
| [에이블스쿨] 제어문과 함수 (2) | 2024.03.04 |
| [에이블스쿨] 컨테이너 자료형 (0) | 2024.03.02 |
| [에이블스쿨] 자료형 (0) | 2024.02.29 |