회사 주식에 투자하고자 합니다. 하지만 보수적인 나는 변동성이 크지 않은 회사를 골라 안정적인 투자를 희망합니다. 이를 위해 2가지 회사로 좁혔고 A,B회사의 6일간 주가 데이터를 수집하였습니다. Numpy 혹은 Pandas를 이용하여 회사의 변동계수를 구해봅시다.
cv_a_np : a 회사의 변동계수cv_b_np : b 회사의 변동계수
- 변동계수 = 표준편차 / 평균
- 표본 표준편차는 자유도를 설정해야 함.
import numpy as np
com_a = [76300, 77400, 77900, 77200, 76900, 78800]
com_b = [6400, 7000, 7400, 6900, 7300, 7600]
# 평균 구하기
a_mean = np.mean(com_a)
b_mean = np.mean(com_b)
# 표본표준편차 구하기
a_std = np.std(com_a, ddof = 1)
b_std = np.std(com_b, ddof = 1)
cv_a_np = a_std / a_mean
cv_b_np = b_std / b_mean
# 결과 출력
print(f'A회사의 변동계수 {cv_a_np:.3f}')
print(f'B회사의 변동계수 {cv_b_np:.3f}')
결과:
A회사의 변동계수 0.011
B회사의 변동계수 0.060
- np.std(ddof = 0)
- pd.Series.std(ddof = 1)
평균이 이고 표준편차가 인 정규분포를 따르는 모집단에서 크기가 25인 표본을 추출하여 평균을 계산하였더니 가 42.7 이다. 이때 에 대한 95% 신뢰 구간을 구하라.
- 표본의 수가 30보다 작더라도 모표준편차를 알고 있다면 t검정이 아닌 Z검정
- scipy에는 z검정으로 신뢰구간을 구하는 모듈이 없기 때문에 직접 계산해야 함
는 모집단의 표준편차, 은 표본의 개수, 는 우리가 추정하고자 하는 모집단의 평균
import scipy.stats as stats
import numpy as np
# 주어진 값들
sigma = 8 # 모집단의 표준편차
n = 25 # 표본 크기
x_bar = 42.7 # 표본 평균
confidence_level = 0.95 # 신뢰 수준
se = sigma / np.sqrt(n)
lower_bound = x_bar - 1.96 * se
upper_bound = x_bar + 1.96 * se
print(f"95% 신뢰 구간: ({lower_bound:.2f}, {upper_bound:.2f})")
결과:
95% 신뢰 구간: (39.56, 45.84)
- 이분산 t 검정
- 등분산과 정규분포 가정은 생략 가능 (조건에 주어졌으므로)
- scipy.stats.ttest_ind(data1, data2, equal_var = True, alternative = 'greater')로 단측 검정
import numpy as np
from scipy import stats
nature = [44, 44, 56, 46, 47, 38, 58, 53, 49, 35, 46, 30, 31] # 자연적으로 말린 목초
artificial = [35, 47, 55, 29, 40, 39, 32, 41, 42, 57, 51, 39] # 인공적으로 말린 목초
t_stats, p_value = stats.ttest_ind(nature, artificial, equal_var=True, alternative='greater')
print('H0: 귀무가설은 "자연적으로 말린 목초로 사육한 젖소의 우유 생산량과 인공적으로 말린 목초로 사육한 젖소의 우유 생산량에는 차이가 없다." 이다.')
print('H1: 대립가설은 "자연적으로 말린 목초로 사육한 젖소의 우유 생산량이 인공적으로 말린 목초로 사육한 젖소의 우유 생산량보다 많다." 이다.')
print(f't-통계량: {t_stats}')
print(f'p-값: {p_value}')
if p_value < 0.05:
print('귀무가설을 기각합니다.')
else:
print('귀무가설을 기각하지 않습니다.')
결과:
H0: 귀무가설은 "자연적으로 말린 목초로 사육한 젖소의 우유 생산량과 인공적으로 말린 목초로 사육한 젖소의 우유 생산량에는 차이가 없다." 이다.
H1: 대립가설은 "자연적으로 말린 목초로 사육한 젖소의 우유 생산량이 인공적으로 말린 목초로 사육한 젖소의 우유 생산량보다 많다." 이다.
t-통계량: 0.605564440457578
p-값: 0.2753667443616386
귀무가설을 기각하지 않습니다.
click_rate 데이터는 헤드라인별 클릭과 클릭하지 않은 수 에 대한 데이터입니다.
카이제곱 분포로 독립성 검정
import pandas as pd
from scipy import stats
# URL 로 데이터 가져오기
url = "https://raw.githubusercontent.com/gedeck/practical-statistics-for-data-scientists/master/data/click_rates.csv"
click_rate = pd.read_csv(url)
clicks = click_rate.pivot(index='Click', columns='Headline', values='Rate')
display(clicks)
chi2_stat, pvalue, dof, expected = stats.chi2_contingency(clicks, correction=True)
print('H0: 귀무가설은 "헤드라인과 페이지 클릭율에는 관련이 없다." 이다.')
print('H1: 대립가설은 "헤드라인과 페이지 클릭율에는 관련이 있다." 이다.')
print(f'chisq: {chi2_stat}')
print(f'pvalue: {pvalue}')
# 결론
alpha = 0.05 # 유의수준
if pvalue < alpha:
print("귀무가설 기각: 헤드라인과 페이지 클릭율에는 관련이 있다.")
else:
print("귀무가설 채택: 헤드라인과 페이지 클릭율에는 관련이 없다.")
결과:
H0: 귀무가설은 "헤드라인과 페이지 클릭율에는 관련이 없다." 이다.
H1: 대립가설은 "헤드라인과 페이지 클릭율에는 관련이 있다." 이다.
chisq: 1.6659394708658917
pvalue: 0.4347562562343731
귀무가설 채택: 헤드라인과 페이지 클릭율에는 관련이 없다.
Yate's correction
scipy.stats 모듈에서 다음 분포를 생성하고 히스토그램으로 표현하기(subplots권장)binomial_data: 확률 0.5의 시행을 10번 시행했을때 성공할 갯수의 1000개의 표본 생성uniform_data : 시작 0, 끝 10의 표본 1000개 생성normal_data : 표본 1000개 생성plt.subplots(1,3)을 이용하여 동시에 표현하고, bins 는 20개로 설정import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
# scipy를 통한 샘플 생성
# binomial
binomial_data = np.random.binomial(n=10, p=0.5, size=1000)
# uniform
uniform_data = np.random.uniform(0, 10, 1000)
# normal
normal_data = np.random.normal(0, 1, 1000)
# 시각화
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
ax1.hist(binomial_data, bins = 20, color = 'blue')
ax1.set_title('Binomial Distribution')
ax2.hist(uniform_data, bins = 20, color = 'green')
ax2.set_title('Uniform Distribution')
ax3.hist(normal_data, bins = 20, color = 'red')
ax3.set_title('Normal Distribution')
for a in [ax1, ax2, ax3]:
a.set_xlabel('Value')
a.set_ylabel('Frequency')
plt.show()
결과:

numpy.choice 함수를 이용하여 각 분포 평균을 내고 이를 500번 반복하여 표본 평균을 생성해 봅시다. (ex bionmial_data 에서 30개씩 뽑아 500번 반복)num_samples : 표본추출할 횟수sample_means: 딕셔너리 자료형으로 Binomal, Uniform, Normal 의 Key값을 가지며 해당하는 values들은 각 30개씩 복원추출하여 뽑은 샘플의 평균 값을 저장. 이를 총 500번 진행import numpy as np
import matplotlib.pyplot as plt
num_samples = 500
sample_means = {
"Binomial": [],
"Uniform": [],
"Normal": []
}
for i in range(500):
sample_means['Binomial'].append(np.random.choice(binomial_data, 30, replace = True).mean())
sample_means['Uniform'].append(np.random.choice(uniform_data, 30, replace = True).mean())
sample_means['Normal'].append(np.random.choice(normal_data, 30, replace = True).mean())
# 시각화
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
ax1.hist(sample_means['Binomial'], bins = 20, color = 'blue')
ax1.set_title('Sample Mean Distribution (Binomial)')
ax2.hist(sample_means['Uniform'], bins = 20, color = 'green')
ax2.set_title('Sample Mean Distribution (Uniform)')
ax3.hist(sample_means['Normal'], bins = 20, color = 'red')
ax3.set_title('Sample Mean Distribution (Normal)')
for a in [ax1, ax2, ax3]:
a.set_xlabel('Mean Value')
a.set_ylabel('Frequency')
plt.show()
결과:
