오늘도 어제에 이어 통계학 공부를 이어갔다. ADsP 공부를 하면서 지겹도록 복습한 귀무가설에 대한 내용들과 아직도 적응이 안되는 여러 분포와 검정들에 대한 내용들을 배웠다.
정규분포를 따르는 무작위 값 생성
heights = stats.norm.rvs(loc=175, scale=5, size=5000)
heights.mean()
# np.float64(175.12138663450918)
heights.std()
# np.float64(4.9588737381446055)
heights1 = stats.norm.rvs(loc=175, scale=5, size=500000)
heights1.mean()
# np.float64(175.0016360108597)
heights1.std()
# np.float64(4.9991504073228725)
부트스트래핑 코드
np.random.seed(1234)
avgs = pd.Series()
for i in range(1000):
smpl = np.random.choice(a=heights, size=100, replace=True)
avgs.loc[i] = smpl.mean()
avgs.describe().round(2)
# count 1000.00
# mean 175.10
# std 0.49
# min 173.19
# 25% 174.76
# 50% 175.10
# 75% 175.45
# max 176.69
# dtype: float64
stats.norm.pdf(x=175, loc=175, scale=15)
# np.float64(0.02659615202676218)
stats.norm.pdf(x=175, loc=175, scale=10)
# np.float64(0.03989422804014327)
stats.norm.pdf(x=175, loc=175, scale=5)
# np.float64(0.07978845608028654)
stats.norm.pdf(x=[169, 173, 175, 178, 182], loc=175, scale=5)
# array([0.03883721, 0.07365403, 0.07978846, 0.06664492, 0.02994549])
# 각 데이터 확률 곱
stats.norm.pdf(x=[169, 173, 175, 178, 182], loc=175, scale=5).prod()
# np.float64(4.5549448486331744e-07)
# 로그 가능도
np.log(stats.norm.pdf(x=[169, 173, 175, 178, 182], loc=175, scale=5)).sum()
# np.float64(-14.601882228193865)
# 로그 가능도 loc 비교
np.log(stats.norm.pdf(x=[169, 173, 175, 178, 182], loc=185, scale=5)).sum()
# np.float64(-23.80188222819387)
x = range(125, 226)
y1 = stats.norm.pdf(x=x, loc=175, scale=15)
y2 = stats.norm.pdf(x=x, loc=175, scale=10)
y3 = stats.norm.pdf(x=x, loc=175, scale=5)
sns.lineplot(x=x, y=y1, label='Scale: 15')
sns.lineplot(x=x, y=y2, label='Scale: 10')
sns.lineplot(x=x, y=y3, label='Scale: 5')
plt.legend()
plt.show()

stats.norm.cdf(x=185, loc=175, scale=15)
# np.float64(0.7475074624530771)
stats.norm.cdf(x=185, loc=175, scale=10)
# np.float64(0.8413447460685429)
stats.norm.cdf(x=185, loc=175, scale=5)
# np.float64(0.9772498680518208)
cdfs = stats.norm.cdf(x=[165, 185], loc=175, scale=5)
np.diff(cdfs)
# array([0.95449974])
stats.norm.ppf(q=0.748, loc=175, scale=15)
# np.float64(185.02313949588586)
stats.norm.ppf(q=0.841, loc=175, scale=10)
# np.float64(184.9857627061566)
stats.norm.ppf(q=0.977, loc=175, scale=5)
# np.float64(184.9769665508391)
rvs(Random Variates) : 난수 생성
pdf(Probability Density Function) : 확률밀도함수(연속형)
cdf(Cumulative Distribution Function) : 누적분포함수
ppf(Percent Point Functio) : x값 반환
stats.skew(heights)
# np.float64(-0.03668062034777025)
stats.kurtosis : 내부적으로 3을 빼서 정규분포하는 데이터의 첨도를 0으로 반환stats.kurtosis(heights)
# np.float64(-0.07067499523641407)
statistic = 검정통계량pvalue = 유의확률stats.shapiro(heights)
# ShapiroResult(statistic=np.float64(0.9995954653825436), pvalue=np.float64(0.40487292793217))
np.random.seed(1234)
heights = stats.norm.rvs(loc=175, scale=5, size=10000)
stats.anderson(heights)
# AndersonResult(statistic=np.float64(0.35265258232175256), critical_values=array([0.576, 0.656, 0.787, 0.918, 1.092]), significance_level=array([15. , 10. , 5. , 2.5, 1. ]), fit_result= params: FitParams(loc=np.float64(175.08063230023598), scale=np.float64(4.9761483416071846))
# success: True
# message: '`anderson` successfully fit the distribution to the data.')
그림(히스토그램, 커널밀도추정), Q-Q Plot
왜도, 척도 확인
샤피로-윌크 & 앤더슨-달링
def scale(x, loc, scale):
return (x - loc) / scale
scale(x=185, loc=175, scale=15)
# 0.6666666666666666
scale(x=185, loc=175, scale=10)
# 1.0
scale(x=185, loc=175, scale=5)
# 2.0
scale(x=90, loc=75, scale=15)
# 1.0
scale(x=55, loc=40, scale=10)
# 1.5
scaled = scale(x=heights, loc=175, scale=5)
scaled
# array([ 0.47143516, -1.19097569, 1.43270697, ..., -1.05246069,
# -0.4976931 , -0.2560062 ], shape=(10000,))
cond = np.abs(scaled) > 3
cond
# array([False, False, False, ..., False, False, False], shape=(10000,))
outliers = heights[cond]
outliers
# array([157.1824167 , 190.62817574, 190.54817675, 155.59550794,
# 158.61347962, 191.10284213, 158.83247735, 157.82590423,
# 159.91806595, 159.24619206, 190.00573485, 158.67898086,
# 157.0030016 , 158.68108413, 159.25844267, 191.43893949,
# 158.34281695, 155.70665632, 190.18821417, 159.73908333])
locs = np.where(cond)
locs
# (array([ 81, 1307, 1333, 1670, 2053, 2289, 3136, 3924, 4477, 4599, 4712,
# 5274, 5903, 7040, 7510, 7743, 8578, 8650, 9406, 9888]),)
scatterplot 으로 시각화plt.figure(figsize=(12, 4))
sns.scatterplot(
x=range(10000), y=heights, fc='0.9', s=25
)
sns.scatterplot(
x=locs[0], y=outliers, fc='red'
)
plt.axhline(
y=175, linestyle='-', linewidth=1, color='0'
)
plt.axhline(
y=160, linestyle='--', linewidth=1, color='red'
)
plt.axhline(
y=190, linestyle='--', linewidth=1, color='red'
)
plt.show()

검정통계량이 기각역에 위치하면 귀무가설을 기각
양측검정이 단측검정보다 임계값이 높음 → 귀무가설 기각 어려움
| 조건 | 가설검정 | ||
|---|---|---|---|
| 일변량 | 연속형 | 대응 없음 | 단일표본 t-검정(모평균 검정) |
| 일변량 | 연속형 | 대응 있음 | 대응표본 t-검정(차이의 모평균 검정) |
| 일변량 | 범주형 | 단일표본 | 모비율 검정 |
| 일변량 | 범주형 | 두 표본 | 모비율 차이 검정 |
| 이변량 | 연속형-연속형 | - | 상관분석(무상관 검정) |
| 이변량 | 연속형-범주형 | 범주 2개 | 독립표본 t-검정(모평균의 차이 검정) |
| 이변량 | 연속형-범주형 | 범주 3개 이상 | 분산분석 |
| 이변량 | 범주형-범주형 | - | 교차분석(독립성 검정) |
정규성 → 모수적 → 평균(값) 사용
비정규성 → 비모수적 → 중위수(순서) 사용
stats.pearsonr(x=df['Age'], y=df['Price'])
# PearsonRResult(statistic=np.float64(-0.796544729051927), pvalue=np.float64(5.8796109422549815e-279))
pg.corr(x=df['Age'], y=df['Price'])

통계 보는 순서
p-val(CI95%) → r → power
lambda 사용x = df['Age']
corr = lambda x: pg.corr(x=x, y=df['Price'])['p-val']
corr(x=df['Age'])
# pearson 5.879611e-279
# Name: p-val, dtype: float64
apply 사용df_num = df.select_dtypes(include=[int, float])
df_num.head()
# Price Age KM HP CC Doors Weight
# 0 13500 23 46986 90 2000 3 1165
# 1 13750 23 72937 90 2000 3 1165
# 2 13950 24 41711 90 2000 3 1165
# 3 14950 26 48000 90 2000 3 1165
# 4 13750 30 38500 90 2000 3 1170
df_num.apply(func=corr).lt(0.05)
# Price Age KM HP CC Doors Weight
# pearson True True True True False True True
| 구분 | 단일표본 t-검정 | 대응표본 t-검정 | 독립표본 t-검정 |
|---|---|---|---|
| 내용 | 표본 통계량과 모평균 비교 | 짝을 이루는 두 집단의 평균 비교 | 서로 독립인 두 집단의 평균 비교 |
| 기본 가정 | 정규성 | 정규성 | 독립성, 정규성, 등분산성 |
| 정규성 가정 만족X | 윌콕슨 부호순위 검정 | 윌콕슨 부호순위 검정 | 윌콕슨 순위합 검정 |
pvt = pd.pivot_table(
data=df,
values='Price',
index='MetColor',
aggfunc=['count', 'mean', 'std']
)
pvt.columns = pvt.columns.droplevel(1)
pvt

dv : dependent variable(종속변수)pg.normality(data=df, dv='Price', group='MetColor')
# W pval normal
# MetColor
# 1 0.974755 7.062942e-11 False
# 0 0.988074 1.430807e-03 False
pg.homoscedasticity(data=df, dv='Price', group='MetColor')
# W pval equal_var
# levene 5.761315 0.016526 False
등분산 : t-검정
이분산 : Welch의 t-검정
correction : True 시 이분산, False 시 등분산pg.ttest(x=y1, y=y2, correction=True)

pg.mwu(x=y1, y=y2)

워낙 많은 내용이기도 하고, 어려운 내용들이라 공부를 하는데 체력을 너무 많이 쓴 느낌이 들었다. 자격증 공부를 하면서 조금씩 익숙해진 내용들이긴 해도 자세히 파고드니까 여전히 어려웠다. 내일은 알고리즘 문제 관련 특강이 있어서 한숨 돌리면서 자격증 공부와 복습을 꾸준히 해야겠다.