분포
시험 문제에서 ‘데이터의 수를 유지하라’는 등의 별도 지시가 없다면, 파생변수 생성 후 해당 결측치가 포함된 행을 제거(dropna)하는 것이 통계적으로 왜곡이 가장 적은 타당한 접근이다. 평균값 대체(Mean imputation)나 보간법(Interpolation)은 시계열 데이터의 추세와 자기상관성(Autocorrelation)을 훼손하므로 이동평균으로 발생한 결측치 처리에는 절대 사용하지 않는다.
- 3-4번
표본 10개의 분산이 90일 때 신뢰도 95%로 모분산의 신뢰구간을 추정
4번 임상 대상 20명에 대해 혈압약 투약 이전과 이후의 차이가 24, 표준편차 9 신뢰구간 95%, 차이가 존재하는지 확인하려한다
-
4.1 귀무가설과 연구가설을 제시하시오
-
4.2 검정 후 귀무가설 기각 여부 제시
불가능하다. scipy.stats.t.interval은 명시적으로 양쪽 꼬리의 면적을 대칭적으로 차감하여 양측 신뢰구간(Two-sided confidence interval)을 산출하도록 설계된 함수다. 단측 검정(One-sided test)에 따른 단측 신뢰구간(또는 신뢰한계, Confidence bound)을 구하려면 누적분포함수의 역함수인 stats.t.ppf(Percent Point Function)를 직접 호출하여 임계값을 산출해야 한다.
# stats.norm.interval(confidence, loc=평균, scale=표준오차)
ci_z = stats.norm.interval(0.95, loc=hatx, scale=np.sqrt(s2/n))
print(f"5.2 모분산을 알 때 95% 신뢰구간 (Z-분포): {ci_z[0]:.4f} ~ {ci_z[1]:.4f}")
import scipy.stats as stats
import numpy as np
# 파라미터 정의
n = 30
df = n - 1
mean = 50.0
std_err = 2.5 # s/sqrt(n)
alpha = 0.05 # 95% 신뢰수준
# 1. 단측 신뢰상한 (Upper Confidence Bound)
# 기준값(H0) 이하인지 확인할 때 사용
t_crit_upper = stats.t.ppf(1 - alpha, df)
upper_bound = mean + t_crit_upper * std_err
# 2. 단측 신뢰하한 (Lower Confidence Bound)
# 기준값(H0) 이상인지 확인할 때 사용
t_crit_lower = stats.t.ppf(alpha, df) # 음수값 도출
lower_bound = mean + t_crit_lower * std_err주어진 상황은 단위 시간(1년) 동안 평균 10회 발생하는 사건이다.
전화 빈도는 아래와 같은 조건을 가진다.
- 전화가 걸려오는 사건이 독립적이다.
- 특정 시간 동안에 전화가 걸려올 확률이 일정하다.
- 단위 시간 내에 동시에 두 개 이상의 전화가 걸려올 확률은 매우 낮다.
from scipy import stats
lam = 10
poisson_dist = stats.poisson(mu=lam)
expon_dist = stats.expon(scale=1/lam)
| 분포 | 검정 종류 (Tail) | 대립가설 방향 | p-value 산출 코드 (scipy.stats 기준) |
|---|---|---|---|
정규분포 (norm) | 좌측 검정 (Left) | 작다 () | norm.cdf(z) |
정규분포 (norm) | 우측 검정 (Right) | 크다 () | norm.sf(z) |
정규분포 (norm) | 양측 검정 (Two) | 다르다 () | 2 * norm.sf(abs(z)) |
카이제곱 (chi2) | 좌측 검정 (Left) | 작다 () | chi2.cdf(x) |
카이제곱 (chi2) | 우측 검정 (Right) | 크다 () | chi2.sf(x) |
카이제곱 (chi2) | 양측 검정 (Two) | 다르다 () | 2 * min(chi2.cdf(x), chi2.sf(x)) |
통계 3
어느 도시에서 성인 전체의 25%가 흡연자라고 한다. 만약 현재도 이와 비슷한 비율이 유지된다면 1300명의 성인표본에서 흡연자가 317명보다 작을 확률은 얼마인가?
통계 4
어떤 앱 개발 회사가 새로운 게임을 출시했다. 사용자가 게임 내에서 특정 퀘스트를 클리어하는 성공 확률이 0.3이라고 한다.
(1) 사용자가 총 3회의 성공을 하기까지 시도한 횟수가 5회 미만일 확률은 얼마인가?
(2) 사용자가 4번의 퀘스트 클리어 성공을 경험하기까지 평균적으로 몇 번의 를 하는가?
# pmf / pdf / cdf / 분위수함수 (cdf의 역함수, ) / 평균 / 표준편차 / 생존함수 (1-cdf)
# rv.pmf() / rv.pdf() / rv.cdf() / rv.ppf() / rv.mean() / rv.std() / rv.sf()datas = np.array([3.1, 3.3, 3.5, 3.7, 3.9, 4.1, 4.3, 4.4, 4.7])
n, mean, s2 = len(datas), np.mean(datas), np.var(datas, ddof=1)
se2 = s2/n
df = n-1
rv = stats.t(df=8, loc=mean, scale=np.sqrt(se2))
rv.interval(alpha=1-0.05)| Notation | mean, Var | 추정량 | PMF / PDF 수식 | PMF / PDF 의미 | 비고 | |
|---|---|---|---|---|---|---|
| 이산 | , | , | , | 1회 시행의 성공 여부 | ||
| , | , | 번 독립 시행 중 정확히 번 성공할 확률 | n회 독립 시행 중 성공 횟수 | |||
| , | - , - | 번째 성공을 위해 총 번 시행할 확률 | 성공 횟수를 채우기 위한 시행 횟수 | |||
| , 복잡 | - , - | 총 개 중 개를 비복원 추출 시 성공이 개일 확률 | 비복원 추출 성공 횟수 | |||
| , | , | 첫 성공이 번째 시행에서 나타날 확률 | 첫 성공까지의 시행 횟수 | |||
| , | , | 단위 시간/공간 내에 사건이 정확히 번 발생할 확률 | 단위 시간/공간 내 사건 발생 수 | |||
| 연속 | , | , | 평균 를 중심으로 데이터가 나타날 상대적 밀도 | 자연 현상의 데이터 분포 | ||
| 0 () , () | , | 표본 크기가 작을 때 표본평균이 가지는 밀도 형태 | 표본 평균의 추정(소표본) | |||
| () , 복잡 | - , - | - | 두 독립적인 카이제곱 분포의 비율에 대한 밀도 | 두 분산의 비율 비교 | ||
| , | , | 개 표준정규분포 변수들의 제곱합에 대한 밀도 | 분산의 추정 및 적합도 검정 | |||
| , | , | 다음 사건 발생까지 대기시간이 일 밀도 (무기억성) | 사건 발생 간의 시간 간격, 무기억성 | |||
| , | , | 구간 내에서 모든 값이 발생할 밀도가 동일함 | 모든 구간의 확률이 동일 | |||
| , 복잡 | - , - | 형상 모수 에 따라 변하는 고장률(수명) 밀도 | 수명 분석 및 신뢰성 공학 |
-
초기하
- M: 모집단의 총 개체 수 (일반 통계학 교재의 N)
- n: 모집단 내 관심 객체(성공 요소)의 총 개수 (일반 통계학 교재의 K)
- N: 비복원 추출로 뽑는 표본의 크기 (일반 통계학 교재의 n)
- k: 추출된 표본 내 관심 객체의 수, 즉 확률변수 값 (일반 통계학 교재의 x)
-
포아송
- 적어도 2마리가 버려질 확률 =
sf(1) - 포아송-지수 관계
- 사건이 일어날 횟수가 포아송분포를 따른다면 이 사건이 처음 일어나는데 걸리는 시간은 지수분포를 따른다
- 주의: 지수 분포(expon)와 포아송 분포(poisson)는 ‘포아송 과정’이라는 동일한 현상을 다루지만, 측정 대상이 횟수(이산)냐 시간(연속)이냐에 따라 유형이 완전히 갈린다. 이를 혼동하면 분석 설계 자체가 무너진다.
- 적어도 2마리가 버려질 확률 =
-
정규분포
-
-
정규분포는 종 모양의 대칭성을 가지며, 평균 주위의 대부분의 데이터가 모임, 평균(분포중심)과 표준편차(퍼짐정도) 두가지 매개변수에 의해 결정
-
정규분포로 근사할 수 있는 분포가 많은 이유 중 하나는 모집단이 정규분포가 아니더라도 표본 크기가 클 때 표본 평균이 따르는 분포가 정규분포이기 때문 (중심극한정리)
-
-
(df)
-
(df)
-
지수분포 = 무기억성
-
Weibull
- 제품의 수명이나 구성 요소의 수명을 모델링할 때 / 고장률이 시간에 따라 변화하는 시스템의 신뢰성 분석 / 특정 활동이나 이벤트가 발생하기까지의 시간을 예측할 때
- Wb(𝜆,𝑘)로 표기 (𝜆:척도모수,𝑘:형상모수)
| Notation | 파라미터 매핑 설명 | SciPy 객체 생성 코드 | |
|---|---|---|---|
| 이산 | 는 성공 확률(p) | bernoulli(p=p) | |
은 시행 횟수(n), 는 성공 확률(p) | binom(n=n, p=p) | ||
은 목표 성공 횟수(n), 는 성공 확률(p) | nbinom(n=n, p=p) | ||
| : 전체 객체 수 (모집단), : 관심 객체 수, : 추출 횟수 | hypergeom(M=M, n=n, N=N) | ||
는 성공 확률(p) | geom(p=p) | ||
는 평균 발생 횟수(mu) | poisson(mu=lambda_) | ||
| 연속 | 는 평균(loc), 는 표준편차(scale) | norm(loc=mu, scale=np.sqrt(sigma**2/n)) | |
는 자유도(df) | t(df=n-1, loc=mu, scale=np.sqrt(sigma**2/n))) | ||
은 분자 자유도(dfn), 는 분모 자유도(dfd) | f(dfn=d1, dfd=d2) | ||
는 자유도(df) | chi2(df=k) | ||
는 발생률, scale은 평균 대기 시간() | expon(scale=1/lambda_) | ||
는 시작점(loc), 는 구간의 너비(scale) | uniform(loc=a, scale=b-a) | ||
| 는 형상 모수, 는 척도 모수 | weibull_min(c=c, scale=lambda_) |
#
rv_bern = stats.bernoulli(p=mu)
#
rv_bin = stats.binom(n=n, p=mu/n)
# p_val = mu / var
# n_param = (mu**2) / (var - mu)
rv_nb = stats.nbinom(n=n_param, p=p_val)
# mu, n 그리고 모집단 크기 M이 주어졌을 때
M = 1000 # 예시 (외부에서 주어져야 함)
K = int(mu * M / n)
rv_hypergeom = stats.hypergeom(M, K, n)
# mu가 주어졌을 때
rv_geom = stats.geom(p=1/mu)
# mu가 주어졌을 때
rv_pois = stats.poisson(mu=mu)
# mu, var가 주어졌을 때
rv_norm = stats.norm(loc=mu, scale=np.sqrt(var))
# mu, var, n이 주어졌을 때 (단, n > 3)
df_t = n - 1
scale_t = np.sqrt(var * (n - 3) / (n - 1))
rv_t = stats.t(df=df_t, loc=mu, scale=scale_t)
# F-분포의 평균은 분모 자유도 df2에만 의존한다.
# df1은 표본 크기 기준인 n−1로 가정하고,
# df2는 평균을 통해 역산한다. (단, μ>1 조건 필요)
df1 = n - 1
df2 = (2 * mu) / (mu - 1)
rv_f = stats.f(dfn=df1, dfd=df2)
# mu가 주어졌을 때
rv_chi2 = stats.chi2(df=mu)
# mu가 주어졌을 때
rv_expon = stats.expon(scale=mu)
# mu, var가 주어졌을 때
scale_unif = np.sqrt(12 * var)
loc_unif = mu - scale_unif / 2
rv_unif = stats.uniform(loc=loc_unif, scale=scale_unif)
# mu, var가 주어졌을 때
def weibull_equations(p, target_mu, target_var):
c, scale = p
# 형태 모수 c는 양수여야 하므로, 계산 안정성을 위해 절댓값 처리 등을 고려할 수 있음
eq_mu = scale * gamma(1 + 1/c) - target_mu
eq_var = scale**2 * (gamma(1 + 2/c) - (gamma(1 + 1/c))**2) - target_var
return (eq_mu, eq_var)
# 초기값 (c=1.0, scale=mu) 부여 후 방정식 풀이
c_est, scale_est = fsolve(weibull_equations, (1.0, mu), args=(mu, var))
rv_weibull = stats.weibull_min(c=c_est, scale=scale_est)
import scipy.stats as stats
import numpy as np
np.isclose(0.2 , stats.bernoulli.pmf(1,0.2))
if '3개 중 2개가 당첨이며, 1개를 뽑은 상황':
rv = stats.hypergeom(M=3, n=2, N=1)
rv.pmf(0); rv.pmf(1); rv.cdf(2) # 당첨이 0개일 확률 / 당첨이 1개일 확률 / 최대 2개 당첨될 확률
print(np.isclose(rv.cdf(2), rv.pmf(0) + rv.pmf(1) +rv.pmf(2))) 기초 접근
| 검정 목적 | 조건/가정 | 검정 통계량 | 분포 | Python 패키지 솔루션 | |
|---|---|---|---|---|---|
| 평균 | 1s | 모분산 앎 | 표준정규분포 | statsmodels.stats.weightstats.ztest | |
| 1s | 모분산 모름 | t-분포 () | scipy.stats.ttest_1samp | ||
| ind. 2s | 모분산 모름, 등분산 가정 | t-분포 () | scipy.stats.ttest_ind(equal_var=True) | ||
| 모비율 | 1s | 대표본 () | 표준정규분포 | statsmodels.stats.proportion.proportions_ztest | |
| 2s, 차이 | 대표본 () | 표준정규분포 | statsmodels.stats.proportion.proportions_ztest | ||
| 3s+ (동질성) | 각 셀 기대도수 | 카이제곱 분포 () | scipy.stats.chi2_contingency | ||
| 모분산 | 1s | 정규모집단 | 카이제곱 분포 () | scipy.stats.chi2.cdf 또는 sf 활용하여 수기 계산 | |
| 2s | 두 정규모집단 | F-분포 () | scipy.stats.f.cdf 또는 sf 활용 수기 계산 (단순 등분산 검정 목적이면 scipy.stats.levene 또는 bartlett 사용) |
import numpy as np
import scipy.stats as stats
from statsmodels.stats.proportion import proportions_ztest
na = 1000; pa = 0.6
nb = 500; pb = 0.4
p = 800/1500
# 1. 수기 계산 방식 수정 (양측 검정 적용)
z = (pa - pb) / np.sqrt(p * (1 - p) * (1/na + 1/nb))
p_value_manual = 2 * stats.norm.sf(np.abs(z))
# 2. ADP 권장 방식 (statsmodels 라이브러리 활용)
count = np.array([600, 200]) # 양품의 수
nobs = np.array([1000, 500]) # 전체 표본의 수
z_stat, p_val = proportions_ztest(count, nobs, alternative='two-sided')
print(f"수기 계산 p-value: {p_value_manual}")
print(f"statsmodels z-stat: {z_stat}, p-value: {p_val}")원자료 주어지는 경우
제시한 내용은 이항분포의 중심극한정리(CLT)에 따른 정규근사(Normal Approximation)를 이용해 모비율 가설검정을 수행할 때, 측정 단위(Scale)의 통일성을 강조한 것이다.
결론부터 말하자면, ‘빈도수(Count)‘를 기준으로 계산할 것인지, ‘표본비율(Proportion)‘을 기준으로 계산할 것인지 노선을 하나로 정해야 한다. 분자에는 빈도수를 넣고 분모에는 비율의 표준편차를 넣는 식으로 혼용하면 결과값이 완전히 왜곡된다.
import numpy as np
import scipy.stats as stats
df = np.array([3.1, 3.3, 3.5, 3.7, 3.9, 4.1, 4.3, 4.4, 4.7])
n, hatx = df.shape[0], np.mean(df)
# rv = stats.norm(loc=mu, scale=sigma)
rv = stats.norm(loc=0, scale=1)if 'critical value':
# 1. 표준정규분포에서 상위 2.5%(양측 검정 시) 지점의 z값
z_critical = stats.norm.ppf(0.975) # 약 1.96
# 2. 자유도가 10인 t-분포에서 하위 5%(단측 검정 시) 지점의 t값
t_critical = stats.t.ppf(0.05, df=10) # 약 -1.812
# 3. 신뢰수준 95%의 신뢰구간 양 끝단
lower, upper = stats.norm.ppf([0.025, 0.975])
if '1s, 평균 신뢰구간, 모분산 안다 (Z-분포)':
sigma_known = 0.04
se_z = sigma_known / np.sqrt(n)
# stats.norm.interval(confidence, loc=평균, scale=표준오차)
ci_z = stats.norm.interval(0.95, loc=hatx, scale=se_z)
print(f"5.2 모분산을 알 때 95% 신뢰구간 (Z-분포): {ci_z[0]:.4f} ~ {ci_z[1]:.4f}")
if '1s, 평균 신뢰구간, 모분산 모름 (t-분포)':
# 표본표준편차 산출 시 자유도를 잃으므로 ddof=1 (비편향 추정량) 적용
std_sample = np.std(df, ddof=1)
se_t = std_sample / np.sqrt(n)
# stats.t.interval(confidence, df, loc=평균, scale=표준오차)
ci_t = stats.t.interval(0.95, df=n-1, loc=hatx, scale=se_t)
print(f"5.1 모분산을 모를 때 95% 신뢰구간 (t-분포): {ci_t[0]:.4f} ~ {ci_t[1]:.4f}")
원자료 없음
if '1s, 평균 신뢰구간, 모분산 모름 (t-분포)':
# if 't검정, 90% 신뢰구간':
# 주어진 데이터: 자유도, 표준오차 (Standard Error)
mean = 15.5; var = 3.2; n = 12
alpha=0.1; confidence_level = 0.90
df = n-1; se = np.sqrt(var / n)
# stats.t.interval(confidence_level, df, loc=mean, scale=se)
se = np.sqrt(var/n)
# 양측인가, 단측인가?
# 오차한계, 양측이므로 0.05
# t_critical = stats.t.ppf((1 + confidence_level) / 2, df)
t_critical = stats.t.ppf(0.95, 11)
margin_of_error = t_critical * se
ci_lower_manual = mean - margin_of_error
ci_upper_manual = mean + margin_of_error
# print(mean - t_critical*se)
# print(mean + t_critical*se)
# se로서, 정확하다
stats.t.interval(0.90, df=11, loc=15.5, scale=np.sqrt(3.2/12))
if False:
# 쓸 수 없다. 이는 표준오차 (se)가 아닌 표준편차 (sd)임.
# 표본 평균의 신뢰구간을 구한 것이 아니라,
# 평균이 15.5이고 표준편차가 $\sqrt{3.2}$인
# t-분포 자체에서 90%의 데이터가 존재하는 구간
# 표준오차는 항상 표준편차보다 작으므로 (1 이상의 n으로 나누기 때문),
# 두 번째 코드로 산출한 구간이 첫 번째 코드보다 훨씬 넓게(부정확하게) 나올 수밖에 없다.
'''
stats.t.interval(0.9, 11, loc=15.5, scale=3.2)
'''
# if '2s, depen, 처리 전후 차이가 0인지에 대한 검정':
if '이는 처리 전후의 차이 D 를 새로운 표본으로 1s 평균=0 검정과 동일':
# 표본 크기, 차이의 표본 평균 (D_bar), 차이의 표본 표준편차 (s_D)
# 유의수준, 귀무가설 하의 기댓값 (차이가 0)
'''
n, mean_diff, std_diff, alpha, mu_0 = 20, 24, 9, 0.05, 0
se = std_diff / np.sqrt(n)
# 표준오차(SE), 검정 통계량(t-statistic), df 계산
t_stat = (mean_diff - mu_0) / se
df = n-1
'''
n, mean_diff, std_diff, alpha, mu_0 = 20, 24, 9, 0.05, 0
se = std_diff / np.sqrt(n)
# 표준오차(SE), 검정 통계량(t-statistic), df 계산
t_stat = (mean_diff - mu_0) / se
df = n-1
if '임계값':
# 임계값(Critical value) 계산
# ppf(pdf 아님, percent point): 누적 확률에 대한 t값을 반환
# 양측 검정
t_critical_two_tailed = stats.t.ppf(1 - alpha/2, df)
# 우측 단측
t_critical_right_tailed = stats.t.ppf(1 - alpha, df)
# 좌측 단측
t_critical_left_tailed = stats.t.ppf(alpha, df)
if 'pval':
# sf = 1 - cdf, 꼬리 확률에서 수치오차 낮음
p_val = 2 * stats.t.sf(np.abs(t_stat), df)
if '귀무 기각조건':
'''
1. 양측검정 기준, np.abs(t_stat)이 t_critical_two_tailed보다 크거나
2. p_val < alpha 보다 작거나
'''
if '2s, 평균 차이 신뢰구간, 모분산 안다 (Z-분포)':
# if '2s, 평균 차이 신뢰구간, 모분산 안다 (t-분포)':
# if '2표본 ind, 등분산 t검정, 95% 신뢰구간':
mean_A, std_A, n_A = 5.7, 0.03, 100
mean_B, std_B, n_B = 5.6, 0.04, 100
alpha = 0.05
var_A = std_A**2
var_B = std_B**2
if 'norm.sf 활용 (Z-검정 P-value 산출)':
se = np.sqrt(var_A/n_A + var_B/n_B)
zstat = (mean_A - mean_B)/se
# 양측이므로
# pval = stats.norm.sf(zstat)
# norm.sf(x)는 1 - norm.cdf(x)와 동일하며
# 꼬리 확률을 구할 때 수치적으로 더 안정적이다.
pval = 2 * stats.norm.sf(np.abs(zstat))
if 'ttest_ind_from_stats 활용 (T-검정 근사)':
'''
# 굳이?
t_stat, p_val_t = stats.ttest_ind_from_stats(
mean1=mean_A, std1=std_A, nobs1=n_A,
mean2=mean_B, std2=std_B, nobs2=n_B,
# equal_var=False 를 주어 분산이 다름(Welch's)을 반영할 수 있다.
equal_var=False
)
'''
분포 - gof
# 관측 빈도의 총합과 기대 빈도의 총합이 완벽하게 일치하지 않아서 발생
# 나머지 확률을 모두 흡수시켜야 한다
df['is_happened'] = df['최대지연시간'].isin(['5분','10분','15분']).astype(int)
series_obs = df.groupby(['지연일자'])['is_happened'].sum()
obs_freq = series_obs.value_counts().sort_index()
mu = series_obs.mean(); N = len(series_obs)
# 4. 기대 빈도 산출 (PMF 활용)
k_values = obs_freq.index
# (참고) 카이제곱 검정은 관측빈도와 기대빈도의 합이 같아야 하므로,
# 꼬리 부분의 남은 확률을 마지막 범주에 더해주는 보정 작업이 필요할 수 있음
# 5. 핵심 보정: 마지막 범주(k_max)에 나머지 꼬리 확률 모두 더하기
# P(X >= k_max) = 생존함수 sf(k_max - 1)
exp_probs = stats.poisson.pmf(obs_freq.index, mu)
exp_probs[-1] = stats.poisson.sf(k_max - 1, mu)
exp_freq = N * exp_probs
# 5. 카이제곱 검정 수행
stats.chisquare(f_obs=obs_freq.values, f_exp=exp_freq)
Power_divergenceResult(statistic=133.6129589038146, pvalue=5.038056396478644e-25)
| 구분 | 모평균 () | 모비율 () |
|---|---|---|
| 구간추정 (100(1-)% 신뢰구간) | (모를 시 대체) | |
| 검정 통계량 () | ||
| 최소 표본 크기 () 결정 | (모를 시 적용) |
-
: error margin
-
모평균
- 모집단이 정규분포를 따르고 표준편차 가 알려진 경우, 에 대한 100(1-)% 신뢰 구간(confidence interval)
- 표본의 크기가 크고() 평균과 표준편차가 와 로 주어질 때 에 대한 100(1-)% 신뢰 구간(confidence interval)
-
모비율
-
표본의 크기가 크고(n) 표본비율이 로 주어질 때 모비율 에 대한 100(1-)% 신뢰 구간(confidence interval)
- 의 분포는 를 따르고 표본의 크기가 크다면 평균은 , 분산은 인 정규분포를 따른다
-
표본의 크기가 클 때 모비율 p에 대한 가설 를 검정 하기 위한 검정통계량
- 구간 추정에서는 se를 구할 때 , 통계 검정시에는 를 사용한다
-
표본크기 결정에 1/4 를 쓰는 이유는, p 가 주어지지 않았을때 의 최댓값 (max) 이기 때문
-