Notice
Recent Posts
Recent Comments
Link
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

Silver bullet

교차 검정 (p-value) 본문

AI/AI

교차 검정 (p-value)

밀크쌀과자 2024. 7. 4. 15:47

1. 교차분석의 실습과 시각화

import pandas as pd
import seaborn as sns

import scipy as sp
from scipy import stats # statistics

import warnings
warnings.filterwarnings("ignore") # 불필요한 Warning 메시지를 꺼줍니다.

df = pd.read_csv('cosmetics_.csv', encoding='utf-8')
df.head()
# 교차표 (cross-table)

pd.crosstab(df.propensity, df.skin, margins=True) # margin : 합계에 해당하는 "All" 추가 여부

# skin & propensity 1열의 각 범주의 의미 (아래 셀 참고)
# Categorical 열 : 범주형 열 <-> Numerical열 : 산술연산열
# propensity : 구매 성향 (비교적 저렴한 제품, 중간 정도의 제품, 비교적 고가의 제품)
# skin : 피부 타입 (건성, 민감성, 중성, 지성/여드름성, 복합성)

crosstab = pd.crosstab(df.propensity, df.skin, margins=True)

crosstab.columns=["건성", "민감성", "중성", "지성", "여드름성", "합계"]
crosstab.index=["비교적 저렴한 제품", "중간정도의 제품", "비교적고가의 제품", "합계"]
crosstab

pd.crosstab(df.propensity, df.skin, margins=True, normalize=True) # 비율값 출력

독립성 검정

- 귀무가설 (돌아갈 귀, 없을 무) (== Mull hypothesis == 영가설)
- 귀무가설 : 구매 성향에 따라 피부 타입에 차이가 없다. (independent, 구매 성향 <-> 피부 타입, vice versa)
- 대립가설 : 구매 성향에 따라 피부 타입에 차이가 있다. (not independent)

- (대립가설이 우리가 세우는 가설, 귀무가설을 자동으로 설정되는 가)

- p-value가 0.05 이하 -> 유의미한 차이가 있다. (not independent) 

# Chi-square 검정 
# 두 범주형 변수 사이의 관계가 있는지 없는지를 검정 (독립성 검정)

stats.chi2_contingency(pd.crosstab(df.propensity, df.skin))[1] # 2번째 return 값이 p-value에 해당

 

+ p-value에 대하여

  • 관찰 데이터의 검정 통계량이 귀무가설을 지지하는 정도
  • 귀무가설이 참이라는 전제 하에(조건), "관찰이 완료된 값 혹은 그보다 더 극단적인 값"이 표본(샘플데이터)을 통해 나타날 (조건부)확률
  • p-value가 0.05(5%) 미만일 경우 = 귀무가설이 참일 때 해당 관측치가 나타날 확률이 매우 낮다고 판단하며, 귀무가설을 기각한다.
  • p-value가 0.05(5%) 이상일 경우 = 귀무가설이 참일 때 해당 관측치가 나타날 확률이 충분하다고 판단하며, 귀무가설을 기각하지 않는다.
    ex) p-value가 0.209일 경우, 귀무가설이 참일 때 이번 실험의 측정치(a 그룹의 b 수치 평균값)가 나타날 확률이 20%가 넘는다.
    == 귀무가설이 참이라는 전제 하에 충분히 가능(by chance or sampling variability)한 결과이다. (귀무가설 기각 X)
  • p-value가 0.05 이하라면 귀무가설을 기각할 수 있음
  • p-value가 0.05 이하라는 것이 항상 대립가설이 맞다(연구 결과가 참이거나 효과가 있다)는 것을 뜻하는 것은 아님을 유념
  • p-value가 0.05(5%) 이하일 때 귀무가설을 기각한다는 것은, 다시 말해 5% 만큼 귀무가설이 참일 가능성(확률)이 있다는 말이기도 하다.
    + 귀무가설이 참인데도 불구하고 이를 기각하는 것이 위험하거나 큰 비용이 발생하는 경우, 유의수준 alpha(ex. 0.05)의 값을 더욱 작게 낮출 수 있다. (ex. 0.01)
  • + p-value의 높고 낮음과 별개로 실제 실험의 효과 크기 역시도 중요하게 고려해야한다.
    예를 들어 어떤 웹사이트의 구매 버튼의 디자인을 변경하여 구매 수가 n 만큼 증가되었고,
    디자인 변경 전/후에 대한 구매 버튼 클릭 수 사이의 관계를 대상으로 통계 검정 후 p-value가 0.05보다 낮게 나왔더라도,
    정작 증가된 구매 수에 해당하는 n이 미미하다면 낮은 p-value에도 불구하고 디자인 변경의 실질적인 효용이 적기 때문이다.
    (통계적으로만 유의미할 뿐 독립변수의 변화에 따른 종속변수의 변화값이 실질적/실용적인 의미를 갖지 않음)
ct = pd.crosstab(df.propensity, df.skin, margins=True)

ct.plot.bar(stacked=True)
# ct.plot(kind='bar', stacked=True)

ct.plot.bar(stacked=False, figsize=(15, 10))

 

2. 독립표본 t-test 분석의 실습과 시각화

두 집단간의 평균차이를 검정 (ex. 1반과 2반의 중간고사 영어 성적 평균 사이의 차이)

df = pd.read_csv('cosmetics_.csv', encoding='utf-8')
df.head()

# satisf_al : 전반적인 만족도 (매우 불만족, 불만족, 보통, 만족, 매우 만족)
male = df[ df['gender']==1 ].satisf_al.values # gender가 1인 행들의 satisf_al 열의 값들 (df['column name'].values)
female = df[ df['gender']==2 ].satisf_al.values
df[ df['gender']==1 ]['satisf_al'].mean()
df[ df['gender']==2 ]['satisf_al'].mean()
# T-test for "ind"ependent samples

stats.ttest_ind(male, female) # T-test for the means of two independent samples 

# "서로 다른" 성별 간에 전반적인 만족도의 평균값 사이에 유의미한 차이가 "없다"

# Ttest_indResult(statistic=-0.494589803056421, pvalue=0.6213329051985961)
df.boxplot(column='satisf_al', by='gender')

# kde=False 로 해주어야 각각의 빈도 수에 따른 밀도 함수 그래프를 가리고 평균만 나타낼 수 있음
# fit에 scipy.stats.norm을 지정하여 분포에 대한 그래프 선을 그려줄 수 있음
# hist_kws & fit_kws 는 히스토그램과 fitting line의 서식을 지정하는 keywords

sns.distplot(male, kde=False, fit=stats.norm,
            hist_kws={'color': 'r', 'alpha': 0.2}, fit_kws={'color': 'r'})

sns.distplot(female, kde=False, fit=stats.norm, 
             hist_kws={'color': 'g', 'alpha': 0.2}, fit_kws={'color': 'g'})

 

3. 대응표본 t-test분석의 실습과 시각화

동일한 모집단으로부터 추출된 두 변수의 평균값을 비교 분석 (ex. 1반의 중간고사 영어 성적 평균과 기말고사 영어 성적 평균 사이의 차이)

df = pd.read_csv('cosmetics_.csv', encoding='utf-8')
df[['satisf_b', 'satisf_i']].describe()

# satisf_b : 구매 가격에 대한 만족도 (5점 척도)
# satisf_i : 구매 문의에 대한 만족도 (5점 척도)

*(주의) pvalue = 9.518854506666571e-12 = 0.00000000000951

# T-test for two related samples (동일 대상에 대한 2가지 변수값)

stats.ttest_rel(df["satisf_b"], df["satisf_i"])

# 귀무가설 : 247명의 고객이 평가한 구매 가격에 대한 만족도의 평균은 구매 문의에 대한 만족도의 평균과 차이가 없다.
# 대립가설 : 247명의 고객이 평가한 구매 가격에 대한 만족도의 평균은 구매 문의에 대한 만족도의 평균과 차이가 있다.

# "동일한" 고객 집단이 평가한 구매 가격에 대한 만족도와 구매 문의에 대한 만족도의 평균값 사이에 유의미한 차이가 있다.
# 대립가설 채택

# TtestResult(statistic=-7.15591640102687, pvalue=9.518854506666571e-12, df=246)
# kde=False 로 해주어야 각각의 빈도 수에 따른 밀도 함수 그래프를 가리고 평균만 나타낼 수 있음
# fit에 scipy.stats.norm을 지정하여 분포에 대한 그래프 선을 그려줄 수 있음
# hist_kws & fit_kws 는 히스토그램과 fitting line의 서식을 지정하는 keywords

sns.distplot(df["satisf_b"], kde=False, fit=stats.norm,
            hist_kws={'color': 'r', 'alpha': 0.2}, fit_kws={'color': 'r'})

sns.distplot(df["satisf_i"], kde=False, fit=stats.norm, 
             hist_kws={'color': 'g', 'alpha': 0.2}, fit_kws={'color': 'g'})

 

4. 분산분석의 실습과 시각화

ANalysis Of VAriance -> ANOVA

# decision : 구매동기 (사회적 요인, 심리적 요인, 외모적 요인)
# satisf_al : 전반적인 만족도

anova1 = df[ df['decision']==1 ].satisf_al.values
anova2 = df[ df['decision']==2 ].satisf_al.values
anova3 = df[ df['decision']==3 ].satisf_al.values
# Per'f'orms one-way ANOVA (ANOVA F-test)

stats.f_oneway(anova1, anova2, anova3) # oneway == 독립변수가 1개 ("구매동기")

# 귀무가설 : 구매동기에 따라 전반적인 만족도의 평균값에 차이가 없다.
# 대립가설 : 구매동기에 따라 전반적인 만족도의 평균값 중 적어도 하나는 차이가 있다.

# 3가지 구매 동기에 따른 전반적인 만족도의 평균값 중 적어도 하나는 유의미한 차이가 있다.
# F_onewayResult(statistic=4.732129410493065, pvalue=0.009632034309915024)
sns.distplot(anova1, kde=False, fit=sp.stats.norm, hist_kws={'color': 'r', 'alpha': 0.2}, fit_kws={'color': 'r'})
sns.distplot(anova2, kde=False, fit=sp.stats.norm, hist_kws={'color': 'g', 'alpha': 0.2}, fit_kws={'color': 'g'})
sns.distplot(anova3, kde=False, fit=sp.stats.norm, hist_kws={'color': 'b', 'alpha': 0.2}, fit_kws={'color': 'b'})

 

 

5. 상관관계분석의 실습과 시각화

df_corr = df[['decision', 'satisf_b', 'satisf_i', 'satisf_al', 'repurchase']]

# Correlation

df_corr.corr() # 피어슨 상관계수, -1에 가까울수록 음의 상관관계, 1에 가까울수록 양의 상관관계, 0에 가까울수록 상관관계가 적음
sns.pairplot(df_corr) # 짝지은(pair) plotting

* 범주형 열을 대상으로 상관계수를 계산하는 것은 어렵다

 

iris = sns.load_dataset("iris")
iris = iris.drop('species', axis=1)
iris.head()

iris.corr()
sns.set(style="ticks", color_codes=True)
sns.pairplot(iris, kind="reg") # reg : fit linear regression models to the scatter plots

corr() 함수에서 음의 상관관계가 있다는 수치가 나오더라도 그것을 그대로 믿어서는 안된다. 시각화를 해봄에 따라 음의 상관관계여도 두 개의 그룹으로 나눈다는 전제하에 양의 상관관계를 이룰 수도 있다.

 

Simpson's paradox