11. 가설 검정(t 검정, 상관 분석)

🔗 'Do it! 쉽게 배우는 파이썬 데이터 분석' 책을 기반으로 JupyterLab 환경에서 학습한 내용입니다 _φ(๑╹╹๑)

 

📌 가설 검정


  • 기술 통계: 데이터를 요약해 설명하는 통계 분석 기법
    • ex) 사람들이 받는 월급을 집계해 월급 평균을 계산
  • 추론 통계: 단순히 숫자를 요약하는 것을 넘어 표본으로 모집단을 추론하는 통계 분석 기법
    • 통계적 추정: 모집단의 진짜 특성(ex 평균, 비율)이 어느 정도인지 추론하는 방법
    • 통계적 가설 검정: 모집단에 대한 가설을 세우고, 이를 표본 데이터를 통해 유의 확률을 계산하여 검정하며 모집단을 추론하는 방법 
      1. 가설: 성별에 따른 월급 차이가 있을 것이다.
      2. 기술 통계: 표본 데이터에서 성별에 따라 월급 차이가 있는 것으로 나타난다.
      3. 통계적 가설 검정: 이런 차이가 우연히 발생할 확률을 계산한다.
      4. 결론: 우연히 발생할 확률이 낮다면 모집단에서도 실제로 성별에 따른 월급 차이가 존재한다고 추론한다.

 

 

 

📌 t 검정


  • t 검정: 두 집단의 평균 차이가 모집단 규모에서 통계적으로 유의한 차이인지, 각 집단 표본의 우연에 의해서 일어난 차이인지 알아볼 때 사용하는 통계 분석 기법
    • scipy 패키지 stats 모듈의 ttest_ind(비교할 1차원 배열1, 비교할 1차원 배열2, equal_var = 집단 간 분산 동일 여부) 함수 활용
    • 유의 확률 5%(p-value 0.05) 미만이면 집단 간의 차이가 통계적으로 유의하다고 해석
    • 집단 간 분산을 고려해야 하는 이유: 집단 간 분산 차이로 인해 유의 확률이 왜곡될 수 있다.
      • 더보기

        💣 [상황 예시] 2종 오류가 발생하는 과정

        • A공장 표본: 10, 10, 10, 10 (평균 10시간 / 기복 0)
        • B공장 표본: 14, 14, 2, 2 (평균 8시간 / 널뛰기 심함)

        ❌ 분산을 각각 고려하지 않는 경우:

        B공장의 널뛰기 분산 때문에 전체 오차 잣대가 뚱뚱하게 부풀어 오릅니다.

        • 통계 심판의 오판: "이 배터리 동네는 원래 널뛰기가 심해서 오차는 흔한 일이야. 그러니까 2시간 차이 난 건 그냥 표본 뽑다 생긴 우연이겠네!"
        • 결과: A공장은 단 1초의 오차도 없이 2시간이나 긴 성능을 증명했는데도, B공장의 널뛰기 노이즈에 묻혀 "두 공장 성능 차이 없음"이라는 억울한 판정을 받게 됩니다.

        ⭕ 분산을 고려하는 경우:

        • 올바른 계산: " 분산이 큰 쪽의 자유도를 낮춤 → 기준선이 깐깐해짐 → 2시간의 차이는 절대로 우연일 수 없다! 확실한 진짜 차이다!"라고 올바르게 판정합니다.

        💣 [상황 예시] 1종 오류가 발생하는 과정

        • 집단 A (대형 그룹): N = 100명, 분산이 매우 작음 (1)
        • 집단 B (소형 그룹): N = 10명, 분산이 매우 큼 (100)
        1. 실제 상태: B 그룹의 분산이 100으로 어마어마하게 크기 때문에, 실제 불확실성은 매우 높고 두 그룹 간 평균 차이는 그냥 우연일 가능성이 높습니다.
        2. 등분산 t-검정의 착각: 전통적인 t-검정은 수가 훨씬 많은 A 그룹(N=100)의 작은 분산(1)에 끌려가서, 합쳐진 분산을 실제 B 그룹의 위험도보다 훨씬 작게 측정해 버립니다.
        3. 결과: 분모(불확실성)가 실제보다 왜곡되어 너무 작아집니다.
        4. 판정: t-통계량이 뻥튀기되고 p-value가 0.05 밑으로 떨어지면서 "실제로는 우연인데 유의미한 차이가 있다!"(1종 오류)고 판정하게 됩니다.

 

  • compact 자동차와 suv 자동차의 도시 연비 t 검정 (등분산 가정)
# 파일 불러오기
import pandas as pd
mpg = pd.read_csv('mpg.csv')
# 각각의 도시 연비를 추출하여 변수에 할당
compact = mpg.query('category == "compact"')['cty'] # mpg.query('조건')[['변수명']]은 2차원 배열 형태로 사용 불가!
suv = mpg.query('category == "suv"')['cty']
# t 검정
from scipy import stats

stats.ttest_ind(compact, suv, equal_var = True) # 결과: 2.39*10^(-21)으로 0.05보다 작아 통계적으로 유의함

 

  • 일반 휘발유와 고급 휘발유의 도시 연비 t 검정 (등분산 가정)
regular = mpg.query('fl == "r"')['cty']
premium = mpg.query('fl == "p"')['cty']

stats.ttest_ind(regular, premium, equal_var = True)# 결과: 우연일 확률이 28.75%로 유의하지 않음!

 

 

 

📌 상관 분석


  • 상관 분석: 두 연속 변수가 서로 관련이 있는지 검정하는 통계 분석 기법이며, 상관계수가 1에 가까울 수록 관련성이 크다는 것을 의미하고 양수면 정비례, 음수면 반비례 관계를 의미한다.

 

  • 실업자 수와 개인 소비 지출의 상관관계
# 파일 불러오기
economics = pd.read_csv('economics.csv')

# 상관계수 행렬 생성(2개 이상 변수 가능)
economics[['unemploy', 'pce']].corr()
# 출력 결과: 실업자 수와 개인 소비 지출은 한 변수가 증가하면 다른 변수가 증가하는 정비례 관계

# (상관계수, 유의확률) 출력
stats.pearsonr(economics['unemploy'], economics['pce'])
# 출력 결과: 유의확률이 0.05 미만으로 실업자 수와 개인 소비 지출의 상관관계가 통계적으로 유의하다.

 

  • 상관행렬 히트맵 생성
# 파일 불러오기
mtcars = pd.read_csv('mtcars.csv')

# 상관행렬 만들기
car_cor = mtcars.corr()
car_cor = round(car_cor, 2) # 소수점 둘째자리까지
car_cor

"""
결과 해석
1. mpg(연비)와 cyl(실린더 수)의 상관계수가 -0.85이므로, 연비가 높을수록 실린더의 수가 적은 경향이 있다.
2. cyl(실린더 수)와 wt(무게)의 상관계수가 0.78이므로, 실린더 수가 많을수록 자동차가 무거운 경향이 있다.
"""

# 상관행렬에서 대각선 기준 왼쪽 아래와 오른쪽 위의 값이 대칭이므로 보기 편하도록 중복 제거

# 중복을 제거하기 위한 mask 생성
import numpy as np
mask = np.zeros_like(car_cor) # 상관행렬과 동일한 크기의 0으로 이루어진 배열 생성
mask[np.triu_indices_from(mask)] = 1 # 위쪽 삼각형 영역의 인덱스를 가져온 후, 1로 변환

# 맨 위쪽 행과, 맨 오른쪽 열은 비어있는 결과가 되므로 아예 삭제
mask = mask[1:, :-1] # numpy 배열 접근
car_cor = car_cor.iloc[1:, :-1] # 데이터프레임 인덱스 번호로 접근

# iloc: integer location으로 인덱스 번호로 접근
# loc: 행, 열 이름으로 접근
# 히트맵 생성
sns.heatmap(data = car_cor,
            annot = True,
            cmap = 'RdBu',
            mask = mask,
            linewidths = .5,
            vmax = 1,
            vmin = -1,
            cbar_kws = {"shrink": .5})
            
"""
- data: 상관계수 행렬명
- annot: 상관계수 표시 여부
- cmap: 컬러맵을 의미하며 값이 클수록 진한 색상 (RdBu: 양수는 파란색, 음수는 빨간색)
- mask: 사용할 마스크명
- linewidths: 경계 구분선 추가
- vmax: 가장 진한 파란색으로 표현할 최대값
- vmin: 가장 진한 빨간색으로 표현할 최소값
- cbar_kws: 범례 크기 줄이기
"""