Bartlett 검정
관련된 내용
- Bartlett 검정
- Fligner 검정
- Levene Test
- Breusch-Pegan 검정
Bartlett 검정은 집단(표본)간 분산에 대해 등분산성을 검정합니다. 이 검정은 두 집단 이상의 자료형식에서도 적용할 수 있으므로 t-검정 또는 일원분산분석에 적용할 자료의 등분산성 가정을 위한 검정에 사용합니다.
이 검정은 정규분포에 부합하는 k개의 그룹에 대한 자유도 k-1인 카이자승(χ2) 분포를 기반으로 합니다. 결정기준인 검정 통계량은 식 1과 같이 계산됩니다. χ2 분포를 기반으로 하기 때문에 표본이 정규분포를 따르는 것을 전제조건으로 합니다. 만약 표본이 비정규 분포에서 추출된 표본의 경우 이 검정은 단순히 분포의 비정규성을 검정하는 것일 수 있습니다.
\begin{align}T&=\frac{(N-k)\ln(s^2_p)-\sum^k_{i=1}(N_i-1)\ln(s^2_i)}{1+\frac{1}{3(k-1)}\left(\left(\sum^k_{i=1}\frac{1}{n_i-1}\right)-\frac{1}{N-k} \right)}\\& s^2_i:\, \text{i 레벨(그룹)의 분산}\\& N: \,\text{자료의 크기} \\& k: \,\text{레벨(집단)의 수} \\& s^2_p: \,\text{합동분산(pooled variance)} \end{align} | (식 1) |
합동표준편차(pooled standard deviation) 참조
$$s^2_p=\sum^k_{i=1} \frac{N_i-1}{N-k}s^2_i$$ | (식 2) |
검정의 가설은 다음과 같습니다.
귀무가설(H0): 집단들의 분산이 같다. |
대립가설(Ha): 최소한 두 집단간의 분산이 다르다. |
Bartlett 검정은 scipy.stats.bartlett(smaples...) 함수를 사용할 수 있습니다. 이 함수는 통계량과 유의확률(p-value)를 반환합니다.
예 1)
랜덤수로 이루어진 세 그룹의 등분산성을 검정하기 위해 Bartlett 검정을 실시합니다.
size=(10, 3) np.random.seed(3) x=np.random.randint(0, 100, size=(10, 3)) print(x)
[[24 3 56] [72 0 21] [19 74 41] [10 21 38] [96 20 44] [93 39 14] [26 81 90] [22 66 2] [63 60 1] [51 90 69]]
st, pV=stats.bartlett(x[:,0],x[:,1],x[:,2]) print(f'통계량: {round(st, 3)}, p-value: {round(pV, 3)}')
통계량: 0.157, p-value: 0.925
위 결과는 세 그룹의 분산이 같다는 귀무가설을 기각할 수 없음을 나타냅니다.
예 2)
일정기간의 코스피지수, 코스탁지수, 다우존스지수, 원-달러 환율의 일일 종가의 변화율 자료들의 등분산성을 검정합니다.
kos | kq | dj | WonDol | |
1 | 0.016 | 0.008 | 0.006 | 0.002 |
2 | -0.007 | -0.004 | 0.014 | -0.000 |
3 | 0.021 | 0.008 | 0.007 | 0.000 |
4 | 0.040 | -0.001 | 0.002 | 0.006 |
5 | -0.001 | -0.011 | -0.003 | -0.000 |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
이 자료는 다음 코드에 의해 호출하고 계산합니다.
st=pd.Timestamp(2021,1, 1) et=pd.Timestamp(2024, 5, 30) code=["KS11", "KQ11", "DJI", "USD/KRW"] nme=['kos','kq','dj','WonDol'] da=pd.DataFrame() for i in code: x=fdr.DataReader(i,st, et)['Close'] x1=x.pct_change() da=pd.concat([da, x1], axis=1) da.columns=nme da.index=range(len(da)) da1=da.dropna()
st, pV=stats.bartlett(da1['kos'], da1['kq'], da1['dj'], da1['WonDol']) print(f'통계량: {round(st, 3)}, p-value: {round(pV, 3)}')
통계량: 586.71, p-value: 0.0
위 결과의 매우 낮은 유의확률은 귀무가설을 기각할 수 있음을 나타냅니다. 즉, 각 그룹의 분산은 동일하지 않습니다. 그러나 bartlett 검정은 정규분포에 부합되는 자료들에만 적용할 수 있습니다. 다음 결과와 같이 위 자료들은 정규성을 따르지 않으므로 위 결과는 신뢰할 수 없습니다.
st, pv=np.array([0]), np.array([0]) for i in nme: st1,pv1=stats.shapiro(da1[i]) st=np.append(st, st1) pv=np.append(pv, pv1) re=pd.DataFrame([st[1:], pv[1:]], index=["통계량", "p-value"], columns=nme) np.around(re, 3)
kos | kq | dj | WonDol | |
---|---|---|---|---|
통계량 | 0.991 | 0.985 | 0.984 | 0.978 |
p-value | 0.000 | 0.000 | 0.000 | 0.000 |
위 결과로부터 모든 표본은 정규분포에 부합한다고 가정할 수 없습니다. 정규성 가정을 만족시키기 위해 각 자료들에 대한 표본분포를 구성하여 다시 검정해봅니다.
다음은 각 자료에서 300개의 표본을 추출하여 각 그룹의 평균값만으로 구성된 평균표본분포를 생성위한 코드입니다.
n=len(da1) kos, kq, dj, wd=da1['kos'], da1['kq'], da1['dj'], da1['WonDol'] idx=[np.random.choice(range(n-1), 30, replace=False) for i in range(300)] kos1=[kos.iloc[i].mean() for i in idx] kq1=[kq.iloc[i].mean() for i in idx] dj1=[dj.iloc[i].mean() for i in idx] wd1=[wd.iloc[i].mean() for i in idx]
st_m, pv_m=np.array([0]), np.array([0]) for i, j in zip([kos1,kq1, dj1, wd1], nme): st_m1,pv_m1=stats.shapiro(np.array(i).reshape(-1,1)) st_m=np.append(st_m, st_m1) pv_m=np.append(pv_m, pv_m1) re=pd.DataFrame([st_m[1:], pv_m[1:]], index=["통계량", "p-value"], columns=nme) np.around(re, 3)
kos | kq | dj | WonDol | |
---|---|---|---|---|
통계량 | 0.992 | 0.991 | 0.992 | 0.996 |
p-value | 0.082 | 0.073 | 0.093 | 0.737 |
생성한 각 자료의 표본 분포는 모두 정규성을 만족합니다. 그러나 다음과 같이 각 자료의 분산은 동일하다고 할 수 없습니다.
st, pV=stats.bartlett(kos1, kq1, dj1, wd1) print(f'통계량: {round(st, 3)}, p-value: {round(pV, 3)}')
통계량: 216.939, p-value: 0.0
위 표본샘플 데이터는 모두 정규분포를 따릅니다. 그러므로 각 데이터의 표준화에의해 표준정규분포에 적합시킬 수 있습니다. 즉, 표준화에 의해 4개 분포의 분산은 같아질 것입니다. 다음 코드의 결과는 이를 확인할 수 있습니다.
da2=pd.DataFrame([kos1, kq1, dj1, wd1]).T da2.head(2).round(3)
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 0.001 | 0.001 | -0.001 | 0.000 |
1 | -0.002 | -0.003 | -0.000 | 0.002 |
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler().fit(da2) daN=scaler.transform(da2) print(np.around(daN[:3, :], 3))
[[ 0.466 0.429 -1.068 0.108] [-0.766 -1.131 -0.426 1.85 ] [-0.33 -1.455 -1.218 -0.165]]
st, pV=stats.bartlett(daN[:,0], daN[:,1], daN[:,2], daN[:,3]) print(f'통계량: {round(st, 3)}, p-value: {round(pV, 3)}')
통계량: 0.0, p-value: 1.0
대상 분포들이 정규분포에 부합한다는 가정이 만족되면 표준화에 의해 등분산을 가정하는 것은 합당합니다.
댓글
댓글 쓰기