통계를 가르쳐주신 하정훈 교수님의 블로그 참고
확률변수 다루기
rvs: 랜덤 변량
pdf: 확률밀도함수(Probability Density Function)
cdf: 누적 분포 함수
sf: 생존 함수(1-CDF)
ppf: 퍼센트 포인트 함수(CDF의 역함수)
isf: 역 생존 함수(SF의 역함수)
stats: 반환 평균, 분산, (Fisher’s) 스큐 또는 (Fisher’s) 첨도
moment: 분포의 중심이 아닌 모멘트
scipy
from scipy.stats import norm # norm: 정규확률분포
print(norm.pdf(1)) # pdf: 확률 분포 함수
print(norm.cdf(1)) # cdf: 누적 확률 분포 함수
print(norm.sf(1)) # sf: 생존함수(1-CDF)
print(norm.cdf(1)+norm.sf(1))
print(norm.ppf(norm.cdf(1)), norm.ppf(0.8413447460685429)); # ppf: 확률 분포의 분위수
print(norm.rvs(size=10)) # 임의 난수 size개 생성
# 결과
0.24197072451914337
0.8413447460685429
0.15865525393145707
1.0
1.0 1.0
[ 0.17937386 -0.56137664 0.04134692 0.40640069 0.54560686 -0.33583934
-0.33333319 -1.50424958 0.87519049 1.03110364]
from scipy.stats import t, norm, expon
print(norm.ppf(0.75, loc=5, scale=3))
print(t.rvs(df=10, size=50))
print(expon.pdf(2, scale=1/0.5))
기술통계(descriptive statistics): 데이터의 특성을 한눈에 파악할 수 있도록 데이터를 정리하고 표현하는 방법
기술통계량: 모집단의 특성을 나타내는 통계량. ex) 중심경향: 평균(mean), 중위수(median), 최빈값(mode) / 산포: 분산(variance), 표준편차(standard deviation), 범위(range), 사분위수(IQR) / 분포의 형태: 왜도(skewness), 첨도(kurtosis)
import numpy as np
x = [1,2,3,4,5,6,7,8,9,10]
len(x) # 데이터의 개수
print('평균 = ', np.mean(x)) # 평균
print('분산 = ', np.var(x)) # 분산
print('표본 분산 = ', np.var(x, ddof=1)) # 표본 분산
print('표준편차 = ', np.std(x)) # 표준 편차
print('표본 표준편차 = ', np.std(x, ddof=1)) # 표본 표준 편차
print('최대값 = ', np.max(x)) # 최대값
print('최소값 = ', np.min(x)) # 최소값
print('중앙값 = ', np.median(x)) # 중앙값
print('1사분위수 = ', np.percentile(x, 25)) # 1사분위 수
print('중앙값 = ', np.percentile(x, 50)) # 2사분위 수 = 중앙값
print('3사분위수 = ', np.percentile(x, 75)) # 3사분위 수
print('배열생성 = ', np.linspace(-5,5,5)) # -5에서 5까지 5개의 값을 가진 배열 생성
import pandas as pd
x = [1,2,3,4,5,6,7,8,9]
y = [_**2. for _ in x]
x, y = x+[10], y+[None]
df = pd.DataFrame({'x': x, 'y': y})
display(df.describe())
df.info()
# 결과
x y
count 10.00000 10.000000
mean 5.50000 38.500000
std 3.02765 34.173577
min 1.00000 1.000000
25% 3.25000 10.750000
50% 5.50000 30.500000
75% 7.75000 60.250000
max 10.00000 100.000000
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10 entries, 0 to 9
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 x 10 non-null int64
1 y 9 non-null float64
dtypes: float64(1), int64(1)
memory usage: 288.0 bytes
##############################################
df = pd.Series(x)
len(df) # 데이터의 개수
print('평균 = ', df.mean()) # 평균
print('표본 분산 = ', df.var(ddof=0)) # 분산
print('분산 = ', df.var()) # 표본 분산
print('표본 표준편차 = ', df.std(ddof=0)) # 표준 편차
print('표준편차 = ', df.std()) # 표본 표준 편차
print('최대값 = ', df.max()) # 최대값
print('최소값 = ', df.min()) # 최소값
print('중앙값 = ', df.median()) # 중앙값
print('1사분위수 = ', df.quantile(0.25)) # 1사분위 수
print('중앙값 = ', df.quantile(0.50)) # 2사분위 수 = 중앙값
print('3사분위수 = ', df.quantile(0.75)) # 3사분위 수
정규분포: 연속확률분포 중 가장 대표적 분포로 종모양.
t분포: 평균이 0, 표준편차가 1인 구릉이나 종모양의 좌우대칭 분포. 자유도에 따라 그 모양이 변하고 자유도가 30개 이상이면 표준정규분포와 거의 일치함.
표준분산 이용하여 모평균 추정
- 특징:
1) 평균값 0.
2) 자유도에 따라 분포 모양 변화
3) 자유도가 30미만인 경우 양쪽 끝이 평평하고 두터운 꼬리모양
4) 자유도 증가에 따라 분산 1에 수렴
5) 표본이 30개 이상일 경우 Z분포와 거의 동일
카이제곱분포: 독립적인 확률변수를 각각 제곱힌 후 합한 분포.
모분산 추정에 사용.
- 특징:
1) 항상 양의 값만 가짐
2) 오른쪽 꼬리 형태의 비대칭분포
3) 자유도에 따라 모양 변화
4) 자유도가 커질수록 정규분포에 가까워짐
F분포: 2개의 카이제곱분포하는 확률변수값을 각각의 자유도로 나눈 평균 카이제곲값의 비를 변수값으로 하는 확률변수 분포.
분산의 비율 비교.
- 특징:
1) 확률변수 F는 항상 양의 값만 갖는 연속확률변수
2) 카이제곱분포와 다르게 2개의 자유도
3) 자유도에 따라 분포 모양 변화
4) 오른쪽 꼬리 형태의 비대칭분포
5) 자유도가 커질수록 정규분포에 가까워짐
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import erf #erf: 가우스 오차함수(error function)
mu = 0.0 # 모평군
sigma = 0.5 # 모표준편차
x = np.linspace(-5, 5, 1000)
y = (1 / np.sqrt(2 * np.pi * sigma**2)) * np.exp(-(x-mu)**2 / (2 * sigma**2))
y_cum = 0.5 * (1 + erf((x - mu)/(np.sqrt(2 * sigma**2))))
plt.plot(x, y, label=f'pdf of N({mu:.1f}, {sigma:.1f}$^2$)') # Latex 적용 python이 아닌 matplotlib에서 지원. 별도 라이브러리 존재
plt.plot(x, y_cum, label='cdf of N(%.1f, %.1f$^2$)'%(mu, sigma))
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend(loc='upper left')
plt.show()

import scipy.stats as st
dof = 30
mu = 0.0
sigma = 1.0
x = np.linspace(-5, 5, 1000)
y_normal = st.norm(mu, sigma).pdf(x)
y_t = st.t(dof).pdf(x)
plt.plot(x, y_normal, label='pdf of N(%.1f, %.1f$^2$)'%(mu, sigma))
plt.plot(x, y_t, label='pdf of t(%d)'%dof)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend(loc='upper left')
plt.show()

import plotly.graph_objs as go
import numpy as np
import pandas as pd
import scipy.stats as stats
dof = 10
mu = 0.0
sigma = 1.0
x = np.linspace(-5, 5, 1000)
y_normal = stats.norm(mu, sigma).pdf(x)
y_t = stats.t(10).pdf(x)
fig = go.Figure()
fig.add_scatter(x=x, y=y_normal, name='pdf of N(%d, %d<sup>2 </sup>)'%(mu, sigma))
fig.add_scatter(x=x, y=y_t, name='pdf of t(%d)'%dof)
fig.show()

import numpy as np
import seaborn as sns
rand_norm = np.random.normal(5,2,100)
print(rand_norm[:5])
print(len(rand_norm))
sns.histplot(rand_norm, bins=np.linspace(0, 10, 10), kde=True);
# 결과
[3.74574333 6.61745706 1.83785367 6.08475513 4.07543715]
100

중심극한정리: 표본이 충분히 크면 표본의 값을 모집단의 값처럼 사용할 수 있다.
import numpy as np
# 모집단 생성
from scipy.stats import norm
population1 = np.random.normal(170, 10, 1000)
population2 = norm.rvs(loc=170, scale=10, size=1000)
# 모집단의 평균, 분산, 표준편차
print('모평균 = ', np.mean(population2)) # 평균
print('모분산 = ', np.var(population2)) # 분산
print('모표준편차 = ', np.std(population2)) # 표준 편차
import matplotlib.pyplot as plt
import seaborn as sns
plt.subplot(1,2,1)
sns.histplot(population1, bins=np.linspace(140, 200, 10), kde=True)
plt.subplot(1,2,2)
sns.histplot(population2, bins=np.linspace(140, 200, 10), kde=True)
plt.show()
# 결과
모평균 = 169.775013672695
모분산 = 94.25625021597496
모표준편차 = 9.70856581663713

# 모집단으로 부터 표본의 크기에 따라 샘플링하여 sample에 저장
import random
sample = np.array(random.sample(list(population2),20))
# 표본의 평균, 분산, 표준편차
print('표본평균 = ', np.mean(sample)) # 평균
print('표본분산 = ', np.var(sample, ddof=1)) # 분산, 자유도-1
print('표본표준편차 = ', np.std(sample, ddof=1)) # 표준 편차, 자유도-1
# 결과
표본평균 = 170.15314985143294
표본분산 = 96.92867099409949
표본표준편차 = 9.845235954211534
구간추정
모평균추정(모분산을 모를 경우 분포 적용
from scipy.stats import t
import numpy as np, random
sample = np.array(random.sample(list(population2),20))
# 표본크기와 허용오차수준
n = len(sample)
alpha = 0.05
# 1) 표본평균 계산
x_bar = sample.mean()
print('표본평균 = ', x_bar)
# 2) 신뢰수준에 따른 t값계산(t(n-1) 분포의 오른쪽 꼬리의 누적밀도가 alpha/2가 되는 지점)
t_value_low = t.ppf(alpha/2,df=n-1)
t_value_high = t.ppf(1-alpha/2,df=n-1)
print('t값 = ', t_value_low, t_value_high)
# 3) 표준오차(표본평균의 표준편차)
se = np.std(sample, ddof=1)/np.sqrt(n)
print('표준오차 = ', se)
# 4) 신뢰구간 계산
ci_lower = x_bar-t_value_low*se
ci_upper = x_bar+t_value_high*se
print("신뢰구간 = [%.4f, %.4f]"%(ci_lower, ci_upper))
# 결과
표본평균 = 169.9000252659096
t값 = -2.0930240544082634 2.093024054408263
표준오차 = 1.9289674291023817
신뢰구간 = [173.9374, 173.9374]
# 표본크기와 허용오차수준
n = len(sample)
alpha = 0.05
# 1) 표본평균 계산
x_bar = np.mean(sample)
print('표본평균 = ', x_bar)
# 2) 표준오차(표본평균의 표준편차)
se = np.std(sample, ddof=1)/np.sqrt(n)
print('표준오차 = ', se)
(ci_lower, ci_upper) = t.interval(1-alpha, df=n-1, loc=x_bar, scale=se)
print("신뢰구간 = [%.4f, %.4f]"%(ci_lower, ci_upper))
# 결과표본평균 = 169.9000252659096
표준오차 = 1.9289674291023817
신뢰구간 = [165.8627, 173.9374]
모분산 추정
from scipy.stats import chi2
# 표본크기와 허용오차수준
n = len(sample)
alpha = 0.05
# 1) 표본 표준편차 계산
S = np.std(sample, ddof=1)
print('S = ', S)
# 2) 신뢰수준에 따른 카이제곱값계산
chi2_lvalue = chi2.ppf(1-alpha/2,df=n-1)
chi2_uvalue = chi2.ppf(alpha/2,df=n-1)
print('카이제곱값 = [%.4f, %.4f]'%(chi2_lvalue, chi2_uvalue))
# 3) 신뢰구간 계산
ci_lower = (n-1)*(S**2)/chi2_lvalue
ci_upper = (n-1)*(S**2)/chi2_uvalue
print("신뢰구간 = [%.4f, %.4f]"%(ci_lower, ci_upper))
# 결과
S = 8.626604595711864
카이제곱값 = [32.8523, 8.9065]
신뢰구간 = [43.0395, 158.7543]
예제 보고 풀기
ttest_1samp(): 단일모집단 평균ttest_real(): 단일 모집단 전후 평균 비교ttest_ind(): 두개의 모집단 평균 비교import numpy as np
from scipy.stats import t
n = 100 # 표본 갯수
mu = 1500 # 모평균(귀무가설)
x_bar = 1420 # 표본평균
S = 200 # 표본오차
akpha = 0.05 # 유의수준
# 임계치 계산
c_val = t.ppf(akpha, df=n-1)
print(f"{c_val = }")
# t 검정통계량 계산
stat = (x_bar-mu)/(S/np.sqrt(n))
print(f"{stat = }")
print(f'H1: mu < {mu:,}')
print(f'H0: mu >= {mu:,}')
print(f't-stat = {stat:.4f}, critical value = {c_val:.4f}')
if stat > c_val:
print("Reject_H1")
else:
print("Accept_H1")
# 결과
c_val = -1.6603911559963902
stat = -4.0
H1: mu < 1,500
H0: mu >= 1,500
t-stat = -4.0000, critical value = -1.6604
Accept_H1
예제 및 함수
from scipy import stats
from sklearn.datasets import load_breast_cancer
import numpy as np
# 데이터셋 로딩
data = load_breast_cancer()
# 'mean radius' 특성만 선택
mean_radius = data['data'][:, 0]
# one sample t-test 수행 (귀무가설: mean_radius의 평균은 15)
mu = 15
t_stat, p_value = stats.ttest_1samp(mean_radius, mu)
# 소수점 4자리로 제한하여 출력
print(f"t-statistic: {t_stat:.4f}")
print(f"p-value: {p_value:.4f}")
# p-value 판정
alpha = 0.05 # 신뢰수준 95%
if p_value < alpha:
print(f"평균이 {mean_radius.mean():.2f}이므로 귀무가설을 기각하므로, mean_radius의 평균은 {mu}가 아닙니다.")
else:
print(f"평균이 {mean_radius.mean():.2f}이므로 귀무가설을 채택하므로, mean_radius의 평균은 {mu}일 가능성이 높습니다.")
from scipy import stats
import numpy as np
# 가상의 무게 데이터 (식용 전, 식용 후)
x_before = np.array([82, 54, 74, 75, 71, 76, 70, 62, 77, 75, 72, 83, 78, 74, 68, 76, 75, 75, 75, 71])
x_after = np.array([75, 50, 74, 71, 69, 73, 68, 62, 68, 72, 70, 77, 71, 74, 67, 73, 77, 71, 76, 74])
x_d = x_before-x_after
n = len(x_d) # 표본 갯수
mu = 0 # 모평균
x_bar = x_d.mean() # 표본 평균
S = x_d.std(ddof=1) # 표본 오차
print(f'{x_bar = }, {S = }')
# 임계치 계산
alpha = 0.05 # 유의 수준
c_val = t.ppf(akpha, df=n-1)
print(f"{c_val = }")
# t 검정통계량 계산
stat = (x_bar-mu)/(S/np.sqrt(n))
print(f"{stat = }")
print(f'H1: mu < {mu:,}')
print(f'H0: mu >= {mu:,}')
print(f't-stat = {stat:.4f}, critical value = {c_val:.4f}')
if stat <= c_val:
print("Reject_H1")
else:
print("Accept_H1")
#### 함수 사용
# # t 검정통계량 계산
# t_stat, p_value = stats.ttest_rel(x_before, x_after)
# # 소수점 4자리로 제한하여 출력
# print(f"t-statistic: {t_stat:.4f}")
# print(f"p-value: {p_value:.4f}")
# print(f't-statistic = {stat:.4f}, p-value = {p_value:.4f}')
# if p_value > alpha:
# print("Reject_H1")
# else:
# print("Accept_H1")
from scipy.stats import t
import numpy as np
alpha = 0.05 #유의수준
n_a = 30 #표본 갯수
x_bar_a = 48500 #표본평균
S_a = 3600 #표본오차
n_b = 30 #표본 갯수
x_bar_b = 52000 #표본평균
S_b = 4200 #표본오차
# 합동 표준오차 계산
var_ab = np.sqrt(S_a**2/n_a + S_b**2/n_b)
# 자유도 계산
dof_ab = (S_a**2/n_a + S_b**2/n_b)**2/((S_a**2/n_a)**2/(n_a-1) + (S_b**2/n_b)**2/(n_b-1))
print(f'{dof_ab = }')
# t 검정통계량 계산
stat = (x_bar_a-x_bar_b)/var_ab
print(f'{stat = }')
# 임계치 계산 alpha=0.05
c_val_low = t.ppf(alpha/2,dof_ab)
c_val_high = t.ppf(1-alpha/2,dof_ab)
print(f'{c_val_low = }, {c_val_high = }')
print('H1: mu_a != mu_b')
print('H0: mu_a = mu_b')
print(f'{stat = :.4f}', f'{c_val_low = :.4f}, {c_val_high = :.4f}')
if (stat <= c_val_low) or (stat >= c_val_high):
print('Accept H1')
else:
print('Reject H1')
#### 힘수 사용
# from scipy.stats import ttest_ind
# a = np.random.normal(x_bar_a, S_a, n_a)
# b = np.random.normal(x_bar_b, S_b, n_b)
# stat, p = ttest_ind(a, b)
# print('H1: mu_before > mu_after')
# print('H0: mu_before <= mu_after')
# print('t-stat = %.4f, p = %.4f' % (stat, p))
# if p > 0.05:
# print('Reject H1')
# else:
# print('Accept H1')
from scipy.stats import chi2
alpha = 0.05 #유의수준
n = 30 #표본 갯수
sigma_squared = 1.2 #모분산(귀무가설)
S_squared = 1.7 #표본분산
# Xai2 검정통계량 계산
stat = (n-1)*S_squared/sigma_squared
# 임계치 계산
c_val_l = chi2.ppf(alpha/2,df=n-1)
c_val_u = chi2.ppf(1-alpha/2,df=n-1)
print(f'H1: sigma2_a != {sigma_squared}')
print(f'H0: sigma2_a = {sigma_squared}')
print(f'chi2-stat = {stat:.4f}, critical value = ({c_val_l:.4f}, {c_val_u:.4f})')
# 양측검정
if (stat <= c_val_l) or (c_val_u <= stat):
print('Accept H1')
else:
print('Reject H1')
from scipy.stats import f
alpha = 0.05 #유의수준
n_a = 16 #표본 갯수
#x_bar_a = 78.3 #표본 평균
S2_a = 37.5 #표본분산
n_b = 21 #표본 갯수
#x_bar_b = 76.7 #표본 평균
S2_b = 98.6 #표본분산
# F 검정통계량 계산
stat = S2_a/S2_b
# 임계치 계산
c_val = f.ppf(alpha,n_a-1,n_b-1)
print('H1: sigma2_a/sigma2_b < 1')
print('H0: sigma2_a/sigma2_b = 1')
print('F-stat = %.4f, critical value = %.4f' % (stat, c_val))
if stat >= c_val:
print('Reject H1')
else:
print('Accept H1')
분산분석: 3개 이상의 집단 간 평균을 검정하는 분석
일원분산분석 수식
편차 수식
총 편차 = 집단간 편차+집단내 편차
제곱합 수식
총 제곱합(SST) = 집단간 제곱합(SSB) + 집단내 제곱힙(SSW)
자유도 수식
총제곱합의 자유도 = 집단간 제곱합의 자유도 + 집단내 제곱합의 자유도
분산 수식
총평균제곱(MST) = 총분산
집단간 평균제곱(MSB) = 집단간 분산
집단내 평균제곱(MSW) = 집단내 분산
검정통계량 F값 수식
이원분산분석 주효과 수식
편차 수식
총 편차 = 요인 i에 의한 편차(요인 i의 주효과) + 요인 j에 대한 편차(요인 j의 주효과) + 요인 i와 j에 의하여 설명할 수 없는 편차(오차)
제곱합 수식
총 제곱합(SST) = 요인 i에 의한 제곱합(SSB) + 요인 j에 의한 제곱합(SSB) + 오차제곱합(SSE)
자유도 수식
총제곱합의 자유도 = 요인 i에 의한 집단간 제곱합의 자유도 + 요인 j에 의한 집단간 제곱합의 자유도 + 요인 i와 요인 j에 의한 집단간 제곱합의 자유도
분산 수식
-
검정통계량 F값 수식
요인 i , 요인 j
이원분산분석 주효과와 상호작용효과 수식
편차 수식
총 편차 = 요인 i에 의한 편차(요인 i의 주효과) + 요인 j에 대한 편차(요인 j의 주효과) + 요인 i와 j의 상호작용에 의한 편차(상호작용효과) + 요인 i와 요인 j에 의해 설명되지 않는 집단내 편차(오차)
제곱합 수식
총 제곱합(SST) = 요인 i에 의한 제곱합(SSB) + 요인 j에 의한 제곱합(SSB) + 요인 i와 j에 의한 제곱합(SSB) + 오차제곱합(SSE)
자유도 수식
총제곱합의 자유도 = 요인 i에 의한 집단간 제곱합의 자유도 + 요인 j에 의한 집단간 제곱합의 자유도 + 요인 i와 요인 j에 의한 집단간 제곱합의 자유도 + 오차 제곱합의 자유도
분산 수식
-
검정통계량 F값 수식
요인 i , 요인 j , 요인 i와 요인 j의 상호작용
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.formula.api import ols
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore") # hide warnings
major = ['ma', 'ar', 'en','ma', 'ar', 'ma', 'ar', 'en', 'ma', 'en', 'ma', 'en']
soju = [2.5, 0.5, 2.0, 3.0, 2.0, 2.0, 1.0, 1.0, 1.0, 0.5, 3.0, 1.5]
df = pd.DataFrame({'major': major, 'soju': soju})
print(df[df.major=='ar'])
print(df[df.major=='en'])
print(df[df.major=='ma'])
# the "C" indicates categorical data
formula = 'soju ~ C(major)'
model = ols(formula, df).fit()
print(model.summary())
print(sm.stats.anova_lm(model))
# 불러올 파일의 경로를 filename 변수에 저장
filename = '../data/data_2_2.csv'
# pandas read_csv로 불러오기
df = pd.read_csv(filename)
print(df)
# data 변환
df = df.melt(id_vars=['volumn'],var_name='location', value_name='sales')
print(df)
# the "C" indicates categorical data
formula = 'sales ~ C(volumn) + C(location)'
model = ols(formula, df).fit()
#print(model.summary())
print(sm.stats.anova_lm(model))
# 불러올 파일의 경로를 filename 변수에 저장
filename = '../data/data_2_3.csv'
# pandas read_csv로 불러오기
df = pd.read_csv(filename)
print(df)
# the "C" indicates categorical data
formula = 'sales ~ C(volumn)*C(location)'
model = ols(formula, df).fit()
print(sm.stats.anova_lm(model))
# interaction plot
from statsmodels.graphics.factorplots import interaction_plot
fig = interaction_plot(df.volumn, df.location, model.fittedvalues,
colors=['red','blue'], markers=['D','^'], ms=10)
import matplotlib.pyplot as plt
plt.show()
# Pooling
formula_p = 'sales ~ C(volumn) + C(location)'
model_p = ols(formula_p, df).fit()
print(sm.stats.anova_lm(model_p))
# interaction plot
from statsmodels.graphics.factorplots import interaction_plot
fig = interaction_plot(df.volumn, df.location, model_p.fittedvalues,
colors=['red','blue'], markers=['D','^'], ms=10)
import matplotlib.pyplot as plt
plt.show()
print('\n***** Normality Test *********************************************')
df.boxplot('strength', by='temp')
s,p = shapiro(a1); print('A1: stat = %.4f, p-value = %.4f' %(s, p))
s,p = shapiro(a2); print('A2: stat = %.4f, p-value = %.4f' %(s, p))
s,p = shapiro(a3); print('A3: stat = %.4f, p-value = %.4f' %(s, p))
s,p = shapiro(a4); print('A4: stat = %.4f, p-value = %.4f' %(s, p))
print('************************************************************************')
print('\n***** Equal Variance Test ****************************************')
s,p = bartlett(a1, a2, a3, a4)
print('Bartlett: stat = %.4f, p = %.4f' %(s, p))
s,p = levene(a1, a2, a3, a4)
print('Levene: stat = %.4f, p = %.4f' %(s, p))
print('************************************************************************')
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import seaborn as sns
#define figure size
fig = plt.figure(figsize=(10,10))
#produce regression plots
resid = np.array(model.resid)
fitted = np.array(model.fittedvalues)
# Q-Q Plot
ax1 = plt.subplot(221)
stats.probplot(resid, dist=stats.norm, sparams=(0,1), plot=plt)
plt.xlabel("Residuals")
plt.title("Normal Q-Q Plot")
# Residual Plot
ax1 = plt.subplot(222)
plt.scatter(fitted, resid)
plt.hlines(0,np.min(fitted),np.max(fitted),color="red")
plt.xlabel("Fitted values")
plt.ylabel("Residuals")
plt.title('Residual plot')
# Histogram
ax1 = plt.subplot(223)
sns.histplot(resid,bins=10)
#plt.hist(resid,bins=10,rwidth=0.8)
plt.title("Histogram of Residuals")
# Scale-Location plot
ax1 = plt.subplot(224)
model_norm_residuals_abs_sqrt = np.sqrt(np.abs(resid))
sns.regplot(x=fitted, y=model_norm_residuals_abs_sqrt,
scatter=True,
lowess=True,
line_kws={'color': 'red', 'lw': 1, 'alpha': 0.8})
plt.ylabel("Standarized residuals")
plt.xlabel("Fitted value")
plt.title("Scale-Location plot")
from statsmodels.sandbox.stats.multicomp import MultiComparison
import scipy.stats
comp = MultiComparison(df.strength, df.temp)
# Bonferroni Correction
result = comp.allpairtest(scipy.stats.ttest_ind, method='bonf')
print(result[0])
# Tuckey's Honestly Significant Difference = "진정으로 유의미한 차이"
from statsmodels.stats.multicomp import pairwise_tukeyhsd
hsd = pairwise_tukeyhsd(df['strength'], df['temp'], alpha=0.05)
print(hsd.summary())
상관분석: 변수 간의 상관 관계를 파악하는 분석법
공분산: ,
상관계수: 변수 간의 선형적인 관계 정도와 방향을 정량화 하여 표시하는 지수로 표준화된 공분산. ,
공분산: 변수 간의 공통된 분포를 나타내는 분산으로 변수 간의 선형적인 연관성 정도를 나타냄.
상관계수의 평가: 목적과 자료에 따라 기준은 상이하나 일반적 기준은 다음과 같음
| 상관계수(r) | r값의 해석 |
|---|---|
| 0.2 미만 | 관계가 거의 없음 |
| 0.2 이상 0.4 미만 | 낮은 상관관계 |
| 0.4 이상 0.6 미만 | 비교적 높은 상관관계 |
| 0.6 이상 0.8 미만 | 높은 상관관계 |
| 0.8 이상 | 매우 높은 상관관계 |
통계모형
변수의 종류와 기능적 관계
편상관계수: 제3의 변수가 미치는 영향을 제거 후, 두 변수 간의 순수한 상관관계를 나타내는 계수. 제3의 통제변수를 Z라 할 때, 두 변수 X와 Y간의 편상관계수는 Z가 X와 Y에 미치는 선형효과를 제거 후 남은 자차 간의 상관계수.
교차분석: 명목(서열)척도로 측정된 두 변수 간의 상호연관성을 알아보기 위한 분석 방법. 빈도 수와 기대 빈도의 차이를 분석하여 변수 간 연관성 검증.
import numpy as np
import pandas as pd
import scipy.stats as stats
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
filename = '../data/data_3_1.csv'
df = pd.read_csv(filename)
# 눈금선 포맷
sns.set_theme(color_codes=True)
# 단순 산점도
#sns.scatterplot(x='weight', y='height', data=df)
# 회귀선 포함 산점도 95% 신뢰구간
sns.regplot(x='weight', y='height', data=df)
# Pearson 상관계수 계산 : Pandas
print(df['weight'].corr(df['height'], method='pearson'))
print(df.weight.corr(df.height, method='pearson'))
# Pearson 상관계수 계산 : Scipy
corr, p = stats.pearsonr(df.weight, df.height)
# 상관계수의 유의성 검정
print('H1: rho != 0')
print('H0: rho = 0')
print('r = %.4f, p = %.4f' % (corr, p))
if p > 0.05:
print('Reject H1')
else:
print('Accept H1')
filename = '../data/data_3_2.csv'
df = pd.read_csv(filename)
# Spearman 상관계수 계산 : Scipy
import scipy.stats as stats
corr, p = stats.spearmanr(df.prefer_ord, df.morality_ord)
# 상관계수의 유의성 검정
print('H1: rho != 0')
print('H0: rho = 0')
print('r = %.4f, p = %.4f' % (corr, p))
if p > 0.05:
print('Reject H1')
else:
print('Accept H1')
filename = '../data/data_3_3.csv'
df = pd.read_csv(filename, index_col='telecom')
# Chi2 검정 : Scipy
stat, p, dof, expected = stats.chi2_contingency(observed=df)
print(dof)
print(expected)
print('H1: row and column are dependent')
print('H0: row and column are independent')
print('chi2_stat = %.4f, p = %.4f' % (stat, p))
if p > 0.05:
print('Reject H1')
else:
print('Accept H1')
import pandas as pd
from scipy.stats import chi2_contingency
# 임의의 의료 데이터 (흡연자 및 비흡연자 중에서 폐암 발생 및 미발생 인원)
data = {'흡연 여부': ['흡연', '흡연', '비흡연', '비흡연'],
'질병 발생': ['발생', '미발생', '발생', '미발생'],
'빈도': [30, 70, 10, 90]}
df = pd.DataFrame(data)
# 교차표 생성
cross_tab = pd.crosstab(df['흡연 여부'], df['질병 발생'], values=df['빈도'], aggfunc='sum')
print("교차표:")
print(cross_tab)
# 카이제곱 검정
chi2, p_value, dof, expected = chi2_contingency(cross_tab)
print(f"\n카이제곱 통계량: {chi2:.4f}")
print(f"p-value: {p_value:.4f}")
# 오즈비(Odds Ratio) 계산
odds_ratio = (cross_tab.loc['흡연', '발생'] / cross_tab.loc['흡연', '미발생']) / (cross_tab.loc['비흡연', '발생'] / cross_tab.loc['비흡연', '미발생'])
print(f"\n오즈비: {odds_ratio:.4f}")
# 상대위험도(Relative Risk) 계산
relative_risk = (cross_tab.loc['흡연', '발생'] / (cross_tab.loc['흡연', '발생'] + cross_tab.loc['흡연', '미발생'])) / (cross_tab.loc['비흡연', '발생'] / (cross_tab.loc['비흡연', '발생'] + cross_tab.loc['비흡연', '미발생']))
print(f"상대위험도: {relative_risk:.4f}")
# 결론 도출
if p_value < 0.05:
print("귀무가설을 기각합니다. 흡연 여부와 질병 발생은 독립적이지 않습니다.")
else:
print("귀무가설을 기각하지 않습니다. 흡연 여부와 질병 발생은 독립적입니다.")
import numpy as np
import pandas as pd
import scipy.stats as stats
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
# 데이터
df = pd.DataFrame(
{"weight": [72,72,70,43,48,54,51,52,73,45,60,62,64,47,51,74,88,64,56,56],
"height": [176,172,182,160,163,165,168,163,182,148,170,166,172,160,163,170,182,174,164,160]}
)
# 계산의 편의를 위해 변수명 변경
x = df.weight
y = df.height
# 표본평균 계산
x_bar = x.mean()
y_bar = y.mean()
print('x_bar = %.4f, y_bar = %.4f'%(x_bar, y_bar))
# 제곱합 계산
SS_x = np.sum((x-x_bar)**2)
SS_xy =np.sum((x-x_bar)*(y-y_bar))
print('SS_x = %.4f, SS_y = %.4f'%(SS_x, SS_xy))
# 회귀계수 추정
beta1 = SS_xy/SS_x
beta0 = y_bar-beta1*x_bar
print('y_hat = %.4f + %.4f x_i'%(beta0, beta1))
#### 함수 사용
# 회귀모형 설계: 단순 선형회귀 모형
# formula = 'height ~ weight'
# # statmodels로 회귀분석실시
# # OLS = Ordinary Least Squares(일반 최소 제곱법)
# model = sm.OLS.from_formula(formula, data=df)
# result = model.fit()
# print(result.summary())
# # Outlier
# print('Outliers :')
# outtest = result.outlier_test()
# print(outtest[outtest['bonf(p)']<1])
filename = '../data/data_3_6.csv'
df = pd.read_csv(filename)
# 회귀모형 설계: 다중선형회귀 모형
#formula = 'HeatFlux ~ East + South + North'
formula = 'HeatFlux ~ South + North'
# statmodels로 회귀분석실시
# OLS = Ordinary Least Squares
model = sm.OLS.from_formula(formula, data=df)
result = model.fit()
print(result.summary())
# Outlier
print('Outliers :')
outtest = result.outlier_test()
print(outtest[outtest['bonf(p)']<1])