이변량 분석

이변량 분석은 타겟(y)과 변수(x)와의 관계를 살펴보는 작업이다.

이 작업에서 우리가 세운 가설이 타당한 지를 확인한다.

귀무가설: X와 Y가 관계가 없다.
대립가설: 우리가 세운 가설로, X에 따라 Y가 차이가 있다.

X와 Y가 숫자냐, 범주냐에 따라서 사용하는 도구들이 달라진다.
아래 표를 참고하자(절대적인 기준은 아님).

이미지 출처: https://github.com/DA4BAM/image

수치화 도구에 대한 설명

상관분석

  • 상관관계를 분석하는 것으로, 숫자형(연속형)에 대해서 사용가능하다.

  • 결측치가 존재할 경우 계산되지 않는다.

  • 얼마나 직선으로 값들이 모여 있는지에 대한 수치화이다.

    • 따라서 상관분석의 한계관계가 있지만 직선이 아닌 경우엔 해당 도구로 관계가 없다고 판단될 수 밖에 없다.
  • 상관계수는 r로 표현된다.

  • r은 -1 ~ 1 사이 값이다.

  • r1|r| \approx 1

  • cf) 절대적인 기준이 아니며, 강사님 경험에 의한 대략적인 기준이다.

    • 강한 관계: 0.5<r10.5 \, < \, |r| \, \leq \, 1
    • 중간 관계: 0.2<r0.50.2 \, < \, |r| \, \leq \, 0.5
    • 약한 관계: 0.1<r0.20.1 \, < \, |r| \, \leq \, 0.2
    • (거의) 없음: r0.1|r| \, \leq \, 0.1

T검정(t-test)

  • 범주형 X와 숫자형(연속형) Y일 때 사용가능하다.
    - 그 중에서도 범주형 X의 범주가 2개일 때 사용가능하다.
  • t-test는 결측치가 있으면 계산되지 않는다.
  • t-test로 얻는 t통계량두 평균의 차이를 표준오차로 나눈 값이다.
    • 보통 t2|t| \, \geq \, 2

분산분석(ANOVA, ANalysis Of VAriance)

  • 범주형 X와 숫자형(연속형) Y일 때 사용가능하다.
    • 그 중에서도 범주형 X의 범주가 3개 이상일 때 사용가능하다.
  • ANOVA를 통해 얻는 F통계량분산비이다.
    • (집단분산)(집단분산)\large \frac{(집단 \, 간 \, 분산)}{(집단 \, 내 \, 분산)}
    • 대략 rr \geq 2~3, 즉 2~3 이상이면 차이가 있다고 본다(대립가설 채택).
  • 결측치가 존재하면 계산되지 않는다.

로지스틱 회귀

  • 숫자형(연속형) X와 범주형 Y일 때 사용할 가설검정 도구가 없다.
  • 따라서 로지스틱 회귀를 이용해 p-value를 구하여 검정한다.
    - p-value는 5%(0.05)미만이면 차이가 있다고 본다(대립가설 채택).
  • 로지스틱 회귀는 미봉책으로 너무 믿지는 말자.
  • 결측치가 존재하면 계산되지 않는다.

카이제곱검정

  • 범주형 X와 범주형 Y일 때 사용가능하다.

  • 카이는 그리스문자 XX를 뜻한다.

  • 카이제곱검정카이제곱 분포에 기초한 통계적 방법으로 범주형 변수들 사이에 어떤 관계가 있는 지를 수치화해준다.

  • 관찰된 빈도가 기대되는 빈도와 유의하게 다른지를 검정한다.

    • X2=Σ(관측빈도기대빈도)2기대빈도\large X^{2} = \Sigma \frac{(관측빈도\,-\,기대빈도)^{2}}{기대빈도}
    • cf) 기대빈도: 귀무가설이 참이면 나올 수 있는 값들
  • 카이제곱검정을 통해 얻는 카이제곱통계량은 클수록 기대빈도와 값 차이가 크다는 의미이다.

  • 하지만 수식을 보면 범주 수가 많을수록 카이제곱통계량은 커지게 되어있음을 알 수 있다.

  • 따라서 보통 자유도의 2~3배보다 크면 차이가 있다고 본다.

    • 자유도에 따라서 확률밀도함수 분포가 달라진다.
    • 따라서 카이제곱통계량으로 비교하기 위해선 자유도가 같아야한다.
  • 범주형 변수의 자유도: 범주 수 - 1

    • ex) 범주 수 5개인 경우, 자유도는 4이다.
  • 카이제곱검정에서 자유도: x변수의 자유도 * y변수의 자유도

    • ex) x변수 범주가 5개, y변수 범주가 2개인 경우의 자유도는 (5 - 1) * (2 - 1) = 4이다.
    • 이 경우, 카이제곱통계량이 자유도 4의 2~3배인 8~12보다 크면 차이가 있다고 볼 수 있다.

데이터 불러오기

  • 기본적으로 필요한 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
  • 데이터 불러오기
titanic = pd.read_csv('https://raw.githubusercontent.com/DA4BAM/dataset/master/titanic.0.csv')  # 타이타닉 데이터
air = pd.read_csv('https://raw.githubusercontent.com/DA4BAM/dataset/master/air2.csv')  # 뉴욕시 공기 오염도 데이터

데이터 출처: https://github.com/DA4BAM/dataset

x와 y분할과 train, val, test 셋분할은 여기서 생략하여 진행한다.

X(숫자) → Y(숫자)

시각화

산점도(scatter)

plt.scatter(air['Temp'], air['Ozone'])
plt.show()

또는

plt.scatter(x='Temp', y='Ozone', data=air)
plt.show()

lmplot

  • 이를 사용하면 회귀선도 표현할 수 있다.
sns.lmplot(x='Temp', y='Ozone', data=air)
plt.show()

pairplot

  • 이를 사용하면 모든 숫자형 변수에 대한 산점도를 그려준다.
sns.pairplot(air)
plt.show()

수치화

상관분석

  • 필요한 라이브러리 불러오기
import scipy.stats as spst

튜플로 결과값을 출력한다.
첫 번째 값은 상관계수, 두 번째 값은 p-value이다.

  • 결측치가 존재하면 계산되지 않는다.
  • 상관계수가 -1 또는 1에 가까울수록 강한 상관관계
  • p-value5%(0.05)미만일 경우 x에 따라 y에 차이가 있다고 본다.
spst.pearsonr(air['Temp'], air['Ozone'])

df.corr()

  • df.corr()로 숫자형 변수 전체에 대한 상관계수를 구할 수 있다.
air.corr()

sns.heatmap을 통한 시각화

sns.heatmap(air.corr(), annot=True, annot_kws={'size': 10}, fmt='.2f', cmap='Blues', cbar=False)
plt.show()

X(범주) → Y(숫자)

범주(x)와 숫자(y) 관계를 살펴볼 때 중요한 관점은 평균비교이다.
이때 두 가지를 고려해야한다.

1. 평균이 그 집단을 대표할 수 있는가?
2. 평균이 믿을 만 한가?

이와 관련된 내용은 다음에 다룬다.

시각화

barplot

막대 그래프 가운데에 있는 직선은 error bar신뢰구간을 의미한다.
막대그래프의 높이는 평균을 의미한다.
error bar의 길이에 평균이 위치할 수 있다는 것으로, 길수록 신뢰도가 떨어진다.

  • 두 집단의 평균이 일치하거나 거의 같다면 대립가설을 기각하고 귀무가설 채택

범주 2개

sns.barplot(x="Survived", y="Age", data=titanic)
plt.show()

범주 3개 이상

sns.barplot(x="Pclass", y="Age", data=titanic)  # X와 Y 순서를 바꾸면 옆으로 눕힌 barplot이 됨
plt.axhline(titanic['Age'].mean(), color='r')  # 전체평균(기준)
plt.show()

수치화

t-test(범주 2개)

t통계량은 두 평균의 차이를 표준오차로 나눈 값이다.
보통 t값이 -2보다 작거나, 2보다 크면 차이가 있다고 본다.

  • 필요한 라이브러리 불러오기
import scipy.stats as spst
  • t-test
    • 결측치가 존재하면 계산되지 않는다.
    • 여기선 우선 결측치가 채워졌다고 가정하고 결측치가 없는 데이터들로 진행한다.
temp = titanic.loc[titanic['Age'].notnull()]  # 결측치 제외

died = temp.loc[temp['Survived']==0, 'Age']
survived = temp.loc[temp['Survived']==1, 'Age']

# t-test  # 인자1(평균) - 인자2(평균) = t통계량
spst.ttest_ind(died, survived)

statistic은 t통계량을 의미한다.

ANOVA(범주 3개 이상)

F통계량은 보통 2~3이상이면 차이가 있다고 본다.

# Na값이 있으면 F통계량, pvalue가 NaN
temp = titanic.loc[titanic['Age'].notnull()]

P_1 = temp.loc[titanic.Pclass == 1, 'Age']
P_2 = temp.loc[titanic.Pclass == 2, 'Age']
P_3 = temp.loc[titanic.Pclass == 3, 'Age']

# ANOVA
spst.f_oneway(P_1, P_2, P_3)

statistic은 F통계량(분산비)을 의미한다.

X(숫자) → Y(범주)

시각화

histogram

sns.histplot(x='Age', data=titanic, hue='Survived', bins=16)
plt.show()

densityplot(kdeplot)

common_norm=False를 할 경우, 그래프 각각의 면적 합이 1인 그래프로 그려진다.
True로 하는 것보다 False로 하는 게 분석에 더 적합하다.
cf) `common_norm=True가 디폴트로, 이 경우 모든 그래프 아래 면적 합이 1이다.

sns.kdeplot(x='Age', data=titanic, hue='Survived', common_norm=False)
plt.show()

histogram + muliple='fill'속성

x에 따라 y 클래스별 비율을 비교해볼 수 있다.

  • ex) 나이에 따라 생존여부 비율을 비교해볼 수 있다.
  • multiple='fill'을 안 쓴 확률밀도함수와 같이 본다.
sns.histplot(x='Age', data=titanic, bins=16, hue='Survived', multiple='fill')
plt.axhline(titanic['Survived'].mean(), color='r')
plt.show()

kdeplot + muliple='fill'속성

x에 따라 y 클래스별 비율을 비교해볼 수 있다.

  • ex) 나이에 따라 생존여부 비율을 비교해볼 수 있다.
  • multiple='fill'을 안 쓴 확률밀도함수와 같이 본다.
sns.kdeplot(x='Age', data = titanic, hue ='Survived', multiple = 'fill')
plt.axhline(titanic['Survived'].mean(), color = 'r')
plt.show()

수치화

로지스틱 회귀 모델

숫자형 변수와 범주형 타켓에 맞는 가설검정 도구가 마땅히 없다.
로지스틱 회귀 모델은 미봉책이다.
따라서 너무 믿지는 말자.

  • 결측치가 있으면 계산되지 않는다.

p-value가 5%(0.05)미만이면 차이가 있다고 본다.


  • 필요한 라이브러리 불러오기
import statsmodels.api as sm
  • 로지스틱 회귀 모델을 통한 p-value 구하기
model = sm.Logit(titanic['Survived'], titanic['Age'])
result = model.fit()
print(result.pvalues)

X(범주) → Y(범주)

범주형 x와 범주형 y를 비교분석하기 위해선 먼저 pd.crosstab()을 이용해 교차표를 만들어야한다.

시각화

시각화 결과가 아래와 같다면, 대립가설을 기각하고 귀무가설을 채택한다.
즉, x에 따라 y에 차이가 없다는 것을 의미한다.

이미지 출처: https://github.com/DA4BAM/image

100% Stacked Bar

# 먼저 집계
temp = pd.crosstab(titanic['Sex'], titanic['Survived'], normalize='index')
print(temp)

# temp = temp.reindex(['male', 'female'])  # 원하는 순서대로 정렬

# 집계 후 차트 그리기
temp.plot.bar(stacked=True)
plt.axhline(1 - titanic['Survived'].mean(), color = 'r')  # 전체 사망률
print('전체 생존율: ', titanic['Survived'].mean())

plt.show()

mosaic

  • 필요한 라이브러리 불러오기
from statsmodels.graphics.mosaicplot import mosaic

x축은 각 x의 범주별 전체 데이터에 대한 비율을 나타낸다.

  • ex) Sex의 범주별(male과 female) 승객비율을 나타낸다.

y축은 x의 각 범주별 y의 각 클래스 비율을 나타낸다.

  • 남성/여성 승객 중 사망 또는 생존 비율을 나타낸다.
mosaic(titanic, ['Sex', 'Survived'])
plt.axhline(1 - titanic['Survived'].mean(), color = 'r')  # 전체 사망률

plt.show()

  • cf) 범주 세 개도 mosaic으로 그릴 수 있다.
    • 보통은 2차원(범주 2개)로 그린다.
mosaic(titanic, ['Sex', 'Pclass', 'Survived'])
plt.axhline(1 - titanic['Survived'].mean(), color = 'r')

plt.show()

수치화

카이제곱검정

  • 필요한 라이브러리 불러오기
import scipy.stats as spst
  • 카이제곱검정
# 먼저 집계
table = pd.crosstab(titanic['Survived'], titanic['Sex'])
print('교차표\n', table)
print('-' * 35)

# 카이제곱검정
result = spst.chi2_contingency(table)
print('카이제곱통계량', result[0])  # 자유도의 2~3배보다 크면 차이가 있다는 것
print('p-value', result[1])
print('자유도', result[2])
print('기대빈도\n',result[3])  # 귀무가설이 참이면 나올 수 있는 값들

카이제곱통계량은 자유도의 2~3배보다 크면 차이가 있다.
p-value는 5%(0.05)미만이어야 차이가 있다고 본다.

  • 만약 카이제곱통계량은 자유도의 2~3배보다 크고 p-value가 5% 이상이라면, 대립가설이 틀렸다고 볼 수도 있고 x와 y가 관계는 있지만 약한 관계라고 볼 수도 있다.
  • cf) 기대빈도: 귀무가설이 참이면 나올 수 있는 값

더 찾아보고 공부할 키워드

숫자 → 숫자

  1. 상관계수 공식

범주 → 숫자

  1. 평균은 믿을만한가?
    1. 표준편차와 표준오차
    2. 95% 신뢰구간
    3. 중심극한정리
  2. 분산분석

숫자 → 범주

  1. p-value

범주 → 범주

  1. 카이제곱검정

좋은 웹페이지 즐겨찾기