정규성 검정¶
- 시나리오: 어느 회사의 직원들의 월급 데이터가 있다. 이 데이터가 정규 분포를 따르는지 확인하고 싶다. 주어진 월급 데이터를 사용하여 정규성 검정을 수행하고 결과를 해석하기
- 가설설정
- 귀무가설 :
- 대립가설 :
- 코드 작성 후 p-value 값을 구하시고 정규성 여부를 조건문으로 구하세요
- 귀무가설, 대립가설, 정규성 만족 유무 print() 만들기 (형식 자유)
- 예) print("abc 만족합니다!")
In [73]:
salaries = [3500, 4000, 4000, 4500, 5000, 5000, 5500, 6000, 6500, 7000]
In [ ]:
from scipy import stats
t_statistic, p_value = stats.shapiro(salaries) #
t_statistic, p_value
if p_value >= 0.05:
print("귀무가설 : 데이터는 정규성을 만족합니다!")
else:
print("대립가설 : 데이터는 정규성을 만족하지 않습니다!")
표본평균과 신뢰구간¶
- 중심극한정리: 표본이 30개 이상이면 표준정규분포와 거의 같은 분포가 됨
- 귀무가설(H0): 비교하는 값과 차이가 없다. 동일하다를 기본개념으로 하는 가설
- 가설검성의 결과는 귀무가설을 채택하거나 기각하는 방식으로 결론을 내린다.
- 대립가설(H1): 뚜렷한 증거가 있을 때 주장하는 가설
- 표본평균과 신뢰구간 상한값을 비교했을 때
- 표본평균 < 신뢰구간 : 신뢰구간이 표본평균을 포함하지 않으므로 귀무가설을 기각한다.
- 표본평균 > 신뢰구간 : 신뢰구간이 표본평균을 포함하므로 귀무가설을 채택한다.
In [3]:
import numpy as np
import pandas as pd
import scipy #수치해석 기능을 제공하는 파이썬 패키지
from scipy import stats #확률분포 분석을 위한 서브패키지
Case 1: 감자튀김 문제¶
- 모평균: 130g
- 표본 크기: 14
- 정규성 검정을 거쳐야 한다.
- 여기서는 정규분포를 따르고 있다고 전제.
- 표본평균: 128.45
- H0: 모평균 = 표본평균
- H1: 모평균 > 표본평균
- 모분산은 9 라고 전제한다.
In [4]:
df = pd.read_csv('data/ch11_potato.csv')
print(df.shape)
print(df.head(3))
(14, 1)
무게
0 122.02
1 131.73
2 130.60
In [11]:
#표본평균을 구한다.
sample = np.array(df['무게']) #배열 추출
round(sample.mean(), 2)
#round(df.loc[:, '무게'].mean(), 2) : 이걸로도 됨
Out[11]:
128.45
In [12]:
#정규분포와 신뢰구간 상한값을 구한다.
#stats.norm(): 정규분포에 대한 확률 분포를 표현한다.
#.isf(0.95): 신뢰구간 95%에 대한 상한값
rv = stats.norm(130, np.sqrt(9/14)) #모평균 130, 모분산 9, 표본크기 14
round(rv.isf(0.95), 2)
Out[12]:
128.68
- 표본평균(128.45) < 신뢰구간(128.68)
- 귀무가설 기각. 모평균이 130g보다 작을 가능성이 있다.
가설 검정 개념¶
분포¶
- t 분포
- 검정통계량으로 활용, 표본이 30개 이상이면 표준정규분포와 거의 같은 분포가 됨
- 카이제곱 분포
- 동질성 검정 통계량에 활용, 모평균과 모분산이 알려지지 않은 모집단의 모분산에 대한 가설 검정에 사용
가설검정 용어¶
- 귀무가설(H0): 비교하는 값과 차이가 없다. 동일하다를 기본개념으로 하는 가설
- 가설검성의 결과는 귀무가설을 채택하거나 기각하는 방식으로 결론을 내린다.
- 대립가설(H1): 뚜렷한 증거가 있을 때 주장하는 가설
- 검정통계량: 관찰된 표본으로부터 구하는 통계량, 가설의 진위를 판단하는 기준
- 유의수준: 귀무가설이 기각되는 확률의 크기
- 일반적으로 0.05(5%)나 0.01(1%)를 쓴다.
- 유의확률(p value): 검정통계량보다 작은 값들의 구간 면적.
- 임계값: 유의수준의 경계선상의 값
가설검정 방법¶
- p value가 유의수준보다
- p < 유의수준(작다): 귀무가설 기각. (유의수준 구간 안에 p value가 들어감)
- p > 유의수준(크다): 귀무가설 채택. (유의수준 구간 밖으로 p value가 넘어감)
단측검정과 양측검정¶
- 단측검정
- 한쪽에만 관심이 있는 경우에 사용: A는 B보다 크다 -> A에 관심이 있음
- 감자튀김 케이스 같은 경우
- 양측검정
- 양측 모두에 관심이 있는 경우에 많이 사용: A는 B와 같지 않다.
- 참고: http://www.statedu.com/QnA/79340
In [21]:
#단측검정에서 가설검정
#검정통계량 구하기
s_mean = df.loc[:, '무게'].mean() #표본평균
z = (s_mean - 130)/ np.sqrt(9/14)
print(f'검정통계량: {round(z, 2)}')
#임계값 구하기
rv = stats.norm() #정규분포
a = rv.isf(0.95)
print(f'임계값: {round(a, 2)}')
#p값 구하기
p = rv.cdf(z)
print(f'p값: {round(p, 2)}')
검정통계량: -1.93
임계값: -1.64
p값: 0.03
- 검정통계량(-1.93) < 임계값(-1.64) -> 귀무가설 기각
- p값(0.03) < 유의수준(0.05)
In [26]:
#양측검정에서 가설검정
#검정통계량 구하기
s_mean = df.loc[:, '무게'].mean() #표본평균
z = (s_mean - 130)/ np.sqrt(9/14)
print(f'검정통계량: {round(z, 2)}')
#임계값 구하기
rv = stats.norm() #정규분포
a = rv.interval(0.95) #-------------> 다른 부분. tuple 값이 나옴
print(f'임계값: {a}')
#p값 구하기
p = rv.cdf(z) * 2 #-----------------> 다른 부분
print(f'p값: {round(p, 3)}')
검정통계량: -1.93
임계값: (-1.959963984540054, 1.959963984540054)
p값: 0.053
- 검정통계량(-1.93) > 임계값(-1.96) -> 귀무가설 채택
- p값(0.053) > 유의수준(0.05)
제1종 오류와 제2종 오류¶
- 제1종 오류: 귀무가설이 옳을 때, 귀무가설을 기각하는 오류
- 오탐(False Positive) - 잘못 검출함
- 제2종 오류: 대립가설이 옳을 때, 귀무가설을 채택하는 오류
- 미탐(False Negetive) - 검출할 것을 검출하지 못함.
In [35]:
# 제 1종 오류: 평균이 130인데도 불구하고 평균이 130보다 작다라는 결론을 내리는 상황
rv = stats.norm(130, 3) #정규분포 생성
c = stats.norm().isf(0.95) #신뢰구간 상한값 계산
n_samples = 10000 #시뮬레이션을 수행할 표본의 수는 10000이다.
cnt = 0 #표본 평균이 모평균보다 작을 때 카운트를 기록하는 변수 cnt를 초기화한다.
#시뮬레이션
for _ in range(n_samples):
sample_ = np.round(rv.rvs(14), 2) #크기가 14인 표본을 추출하고 둘째 자리까지 반올림.
s_mean_ = np.mean(sample_) #sample_ 에 저장된 표본의 평균을 계산.
z = (s_mean_ - 130) / np.sqrt(9/14) #검증통계량 계산
if z < c:
cnt += 1 #만약 시뮬레이션 결과가 신뢰구간 상한값보다 작으면/귀무가설 기각이면 cnt에 1 더함
cnt / n_samples #귀무가설이 기각된 경우 / 시뮬레이션 횟수
Out[35]:
0.0507
해석¶
- 시뮬레이션 결과:약 0.052
- 제1종 오류를 범할 비율은 0.52
- 약 5% 확률로 모평균이 130g인데도 불구하고 모평균이 130g보다 작다고 잘못 탐지한다.
- 신뢰구간을 1%로 하여 더 엄격하게 적용할 수 있다.
In [38]:
#제2종 오류:
##실제로 표본평균이 130g보다 작음에도 불구하고 표본평균은 130g보다 작다라는 결론을 얻을 수 없는 상황.
#제1종 오류와 코드는 동일, 실제 모평균이 128이라는 점이 다름
rv = stats.norm(128, 3)
c = stats.norm().isf(0.95)
n_samples = 10000
cnt = 0
for _ in range(n_samples):
sample_ = np.round(rv.rvs(14), 2)
s_mean_ = np.mean(sample_)
z = (s_mean_ - 130) / np.sqrt(9/14)
if z >= c:
cnt += 1
cnt / n_samples
Out[38]:
0.2011
해석¶
- 시뮬레이션 결과: 약 0.2
- 제2종 오류를 범할 비율은 0.2
- 약 20%의 확률로 모평균이 130g보다 작은데도 모평균이 130보다 작다는 결론을 얻을 수 없다.
- 제2종 오류는 모집단의 정보에 의존한다. 그러나 대부분의 경우 모집단의 구체적인 정보를 얻기 어려워 저2종 오류는 컨트롤할 수 없다.
단일표본 가설검정 정리¶
- 모분산을 아는 경우의 모평균 검정
- 모분산에 대한 검정
- 모분산을 모르는 경우 모평균 검정
- 모집단에 대한 정보를 아는 현실 케이스가 더 적기 때문에 대부분 이 케이스를 사용함
In [53]:
#모분산을 알고 있을 때 모평균 검정
#위의 과정의 종합
def pmean_test(sample, mean0, p_var, alpha = 0.05):
s_mean = np.mean(sample)
n = len(sample)
rv = stats.norm()
interval = rv.interval(1 - alpha)
z = (s_mean - mean0) / np.sqrt(p_var/n)
if interval[0] <= z <= interval[1]: #신뢰구간 사이에 있으면
print("귀무가설 채택")
else:
print('귀무가설 기각')
if z < 0:
p = rv.cdf(z) * 2
else:
p = (1 - rv.cdf(z)) * 2
print(f'p값은 {p: .3f}')
sample = np.array(df['무게'])
pmean_test(sample, 130, 9)
귀무가설 채택
p값은 0.053
In [66]:
#모분산에 대한 검정
def pvar_test(sample, var0, alpha = 0.05):
u_var = np.var(sample, ddof = 1) #ddof: 자유도
n = len(sample)
rv = stats.chi2(df = n -1)
interval = rv.interval(1 - alpha)
y = (n-1) * u_var / var0
if interval[0] <= y <= interval[1]:
print("귀무가설 채택")
else:
print('귀무가설 기각')
if y < rv.isf(0.5):
p = rv.cdf(y) * 2
else:
p = (1 - rv.cdf(y)) * 2
print(f'p값은 {p: .3f}')
pvar_test(sample, 9)
귀무가설 채택
p값은 0.085
In [69]:
#모분산을 모를 때 모평균 검정 ----> 디폴트
def pmean_test(sample, mean0, alpha = 0.05):
s_mean = np.mean(sample)
u_var = np.var(sample, ddof = 1)
n = len(sample)
rv = stats.t(df = n-1) #자유도가 1인 t 분포
interval = rv.interval(1 - alpha)
t = (s_mean - mean0)/np.sqrt(u_var/n)
print(f't 통계량 값: {t: .3f}')
if interval[0] <= t <= interval[1]:
print('귀무가설 채택')
else:
print('귀무가설 기각')
if t < 0:
p = rv.cdf(t) * 2
else:
p = (1 - rv.cdf(t)) * 2
print(f'p값은 {p: .3f}')
pmean_test(sample, 130)
t 통계량 값: -1.455
귀무가설 채택
p값은 0.169
In [72]:
#메소드
t, p = stats.ttest_1samp(sample, 130)
round(p, 3)
Out[72]:
0.169
'데이터분석' 카테고리의 다른 글
[selenium] 동적 웹크롤링 루틴 (0) | 2024.02.17 |
---|---|
[통계분석] 다중회귀분석(예제 위주) (0) | 2024.01.19 |
[통계분석] 단순선형회귀분석, 카이제곱검정 (0) | 2024.01.19 |
[통계분석] 2표본 가설검정, 등분산 검정 (0) | 2024.01.18 |
[통계분석] 데이터 분석 연습하기 (0) | 2024.01.17 |