본문 바로가기

코딩으로 익히는 Python/통계

[Python] 5. 모집단과 표본 : 모평균 추정, 중심극한정리

728x90
반응형
SMALL

기술통계

 

분포를 표현하는 또다른 방법은 분포의 특징을 나타내는 여러가지 숫자를 계산하여 그 숫자로서 분포를 나타내는 것이다. 이러한 값들을 기술통계(descriptive statistics)라고 한다. 대표적인 기술통계는 다음과 같다.

  • 표본평균, 표본중앙값, 표본최빈값
  • 표본분산, 표본표준편차
  • 표본왜도, 표본첨도

표본평균

 

표본평균(sample mean, sample average): 데이터 분포의 대략적인 위치를 나타낸다.

 

이 식에서 𝑁은 자료의 개수, 𝑖는 자료의 순서(index)를 뜻한다.


분산과 표준편차

 

데이터가 얼마나 변동(variation)하고 있는지를 알아야 한다. 이러한 정보를 알려주는 특징값이 표본분산(sample variance) 또는 표본표준편차(sample standard deviation)이다. 평균이나 기댓값이 분포의 위치를 대표하는 것이라면 분산은 분포의 폭(width)을 대표하는 값이다. 표준편차는 분산에 대한 양의 제곱근(square root)값이다.

 

표본분산은 다음처럼 구한다.

 

위 식에서 구한 표본분산은 정확하게 말하면 편향오차를 가진 편향 표본분산(biased sample variance)이다. 이와 대조되는 비편향 표본분산(unbiased sample variance)은 다음과 같이 구한다.

 


자유도

 

통계학에서 자유도(degrees of freedom)는 통계적 추정을 할 때 표본자료 중 모집단에 대한 정보를 주는 독립적인 자료의 수를 말한다.
크기가 𝑛인 표본의 관측값의자유도는𝑛−1이다.

 

예제를 통한 자유도 이해

 

다음의 자료를 살펴보자.

10 14 12 18 16

이 자료의 합계는 70이고, 평균은 14이다. 우리는 평균이 14임을 알고 있으므로 만약 위의 숫자 중 하나를 모르더라도 그 숫자를 찾아낼 수 있다. 마지막 숫자 16을 모르고 평균이 14임을 안다고 가정하자. 평균이 14이면 숫자들의 합계가 70인 것도 알 수 있다. 그리고 나머지 4개의 숫자가 각각 10, 14, 12, 18이므로 전체 합계에서 위 4개의 숫자를 빼면 마지막 숫자는 16이라는 것을 알 수 있다.

그러므로 표본평균 값을 알고 있으면 전체 자료 중 자유롭게 값을 취할 수 있는 관찰치의 개수는 4개인 것이다.

그러면 모집단분산의 계산에서는 자유도가 N인데, 왜 표본분산에서는 n-1인가? 분산을 계산하기 위해서는 자료의 중심인 모집단평균을 사용해야 하지만, 표본에서는 모집단평균을 알 수가 없으므로 표본평균을 모집단평균 대신에 사용한다. 그러나 표본평균이 모집단평균과 일치한다고 볼 수는 없다. 그리고 표본평균은 표본자료에서 계산되었으므로 전체 자료 중 분산의 계산에는 n-1개만 사용된다고 할 수 있다.

 

※ 출처 : 위키백과


파이썬을 사용한 표본분산 및 표본표준편차의 계산

 

파이썬에서 표본분산과 표본표준편차를 구할 때는 다음 함수를 사용한다. ddof 인수를 이용하면 비편향 표본분산과 표본표준편차를 구할 수 있다.

  • var()
  • std()

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
import scipy.stats as st

 

데이터 불러오기 (pd.read_csv)

python 파일 경로에 data3 폴더 만든 후 다음의 ch4_scores400.csv파일 넣어놓기

ch4_scores400.csv
0.00MB

df = pd.read_csv('data3/ch4_scores400.csv')
scores = np.array(df['score'])
scores[:10]
[OUT] :

array([76, 55, 80, 80, 74, 61, 81, 76, 23, 80], dtype=int64)

 

df

 

scores.mean()
[OUT] :

69.53

 

len(df)
[OUT] :

400

임의로 표본 추출

 

np.random.choice([1,2,3,4,5,6,7,8,9,10],3) # 임의로 3개 추출 default가 복원추출
[OUT] :

array([3, 9, 8])

 

np.random.seed(0) # 똑같은 random 결과를 얻기 위해서
sample = np.random.choice(scores,20)
print(sample)
print(sample.mean())
[OUT] :

[49 60 72 86 52 61 77 91 80 56 69 67 90 56 75 79 60 79 68 81]
70.4

 

sample.var() # np.var(sample) # 편향 표본 분산
[OUT] :

150.34000000000003

 

sample.std() # np.std(sample) # 편향 표본 표준편차
[OUT] :

12.261321299109653

 

sample.var(ddof=1) # 비편향 표본분산 (자유도 적용)
[OUT] :

158.25263157894742

 

for i in range(5):
    sample1 = np.random.choice(scores,20)
    print(i+1,"표본평균", sample1.mean())
[OUT] :

1 표본평균 70.7
2 표본평균 71.9
3 표본평균 71.25
4 표본평균 67.4
5 표본평균 67.7

 

plt.hist(scores, bins=100, range=(0,100)) 
plt.show()

 

plt.xlabel('score')
plt.ylabel('relative frequency')
plt.hist(scores, bins=100, range=(0,100), density=True) # density = True면 상대도수
plt.xlim(20,100)
plt.show()

 

sample2 = np.random.choice(scores, 10000)
plt.hist(sample2,bins=100,range=(0,100),density=True)
plt.xlim(20,100)
plt.show()


표본이 충분히 크면 모집단에 가까워짐

 

n = 20
nSample = 100 # 20개(n)의 표본 100개를 추출한 것
# np.random.seed(0)
sample_mean = np.array([np.random.choice(scores,n,).mean() for _ in range(nSample)])
sample_mean
[OUT] :

array([68.85, 69.4 , 73.6 , 72.  , 71.8 , 65.8 , 74.85, 68.6 , 72.6 ,
       66.8 , 64.8 , 62.5 , 61.1 , 68.95, 70.8 , 68.15, 67.65, 67.7 ,
       70.8 , 71.75, 75.8 , 71.1 , 71.55, 74.55, 72.5 , 69.85, 66.15,
       71.95, 65.6 , 64.75, 71.9 , 60.1 , 70.05, 72.3 , 69.8 , 73.5 ,
       75.  , 70.1 , 70.45, 68.95, 69.25, 72.4 , 65.9 , 71.65, 64.95,
       68.3 , 70.25, 67.15, 70.95, 69.3 , 70.35, 68.15, 68.9 , 68.85,
       69.75, 70.5 , 73.3 , 74.7 , 66.8 , 66.85, 63.15, 71.4 , 66.75,
       68.6 , 69.6 , 72.75, 71.3 , 66.8 , 74.95, 71.  , 63.75, 69.65,
       68.45, 64.9 , 73.  , 70.2 , 70.95, 70.65, 72.65, 64.5 , 71.55,
       73.1 , 68.6 , 71.  , 72.15, 65.  , 66.85, 66.6 , 69.15, 65.95,
       69.5 , 73.65, 74.8 , 71.9 , 70.05, 71.75, 71.75, 67.6 , 64.35,
       71.05])

 

scores.mean()
[OUT] :

69.53

 

sample_mean.mean() # 표본평균의 평균값
[OUT] :

69.59750000000001

 

# 모평균
print(scores.mean())
# 표본평균의 평균
print(sample_mean.mean())
# 모분산/n
print(scores.var()/n)
# 표본평균의 분산
print(sample_mean.var())
# 표본평균의 편차 (SEM : standard error of the mean)
print('SEM :', scores.std()/math.sqrt(n))
print( sample_mean.std() )
[OUT] :

69.53
69.7655
10.333454999999999
11.59108475

모평균 추정

신뢰구간 1.96(95%신뢰도), 2.58(99%신뢰도)

 

 

평균의 표준 오차(standard error of the mean, SEM)

 

 

n=30
sample1 =   np.random.choice(scores,n)
sMean = sample1.mean()
sStd = sample1.std()
print('모평균',scores.mean())
print('표본평균',sMean)
print('모편차',scores.std())
print('표본편차',sStd)
[OUT] :

모평균 69.53
표본평균 68.16666666666667
모편차 14.375990400664575
표본편차 13.234005020736877

 

a = sMean - 1.96*(scores.std()/math.sqrt(n))
b = sMean + 1.96*(scores.std()/math.sqrt(n))
print(a)
print(b)
# 95& 신뢰로 모평균은 63점 ~ 73점 사이에 존재(추정)
print('신뢰구간 :',b-a)
[OUT] :

63.02228457043782
73.31104876289552
신뢰구간 : 10.288764192457705

 

st.norm.interval(0.95, sample1.mean(), scale=st.sem(sample1,ddof=0))
# 95& 신뢰로 모평균은 63점 ~ 73점 사이에 존재(추정)
[OUT] :

(63.4310258104615, 72.90230752287185)

연습문제

 

1. 어느 호수의 납의 농도는 표준편차가 3mg/L이다. 이 호수에서 납의 농도를 16번 측정한 결과 평균 농도는 18mg/L 이었다. 이 호수에서 납의 농도에 대한 모평균 m 의 신뢰도 95%의 신뢰구간을 구하여라.

 

2. 어느 고등학교 남학생 36명의 제자리멀리뛰기 기록은 평균이 216cm 표준편차가 10cm이었다. 이 학교 남학생들의 제자리 멀리뛰기 기록에 대한 모평균 m의 신뢰도 99% 신뢰구간을 구하여라.


Solution

 

1. 어느 호수의 납의 농도는 표준편차가 3mg/L이다. 이 호수에서 납의 농도를 16번 측정한 결과 평균 농도는 18mg/L 이었다. 이 호수에서 납의 농도에 대한 모평균 m 의 신뢰도 95%의 신뢰구간을 구하여라.

 

pbStd = 3
pbMean = 18
n = 30
a = pbMean - 1.96*(pbStd/math.sqrt(n))
b = pbMean + 1.96*(pbStd/math.sqrt(n))
print(a)
print(b)
print('신뢰구간 :',a,'~',b)
print('신뢰구간 길이 :',b-a)
[OUT] :

16.926463787289876
19.073536212710124
신뢰구간 : 16.926463787289876 ~ 19.073536212710124
신뢰구간 길이 : 2.147072425420248

 

2. 어느 고등학교 남학생 36명의 제자리멀리뛰기 기록은 평균이 216cm 표준편차가 10cm이었다. 이 학교 남학생들의 제자리 멀리뛰기 기록에 대한 모평균 m의 신뢰도 99% 신뢰구간을 구하여라.

 

# 모편차를 모르지만 표본의 갯수가 30개 이상이어서 모편차 == 표준편차
mStd = 10
mMean = 216
n = 36
a = mMean - 2.58*(mStd/math.sqrt(n))
b = mMean + 2.58*(mStd/math.sqrt(n))
print(a)
print(b)
print('신뢰구간 :',a,'~',b)
print('신뢰구간 길이 :',b-a)
[OUT] :

211.7
220.3
신뢰구간 : 211.7 ~ 220.3
신뢰구간 길이 : 8.600000000000023

중심극한 정리 : 표본의 크기가 클 때 정규분포 형태에 가까워진다.

 

n = 20
nSample = 10000
sample_mean = np.array([np.random.choice(scores,n,).mean() for _ in range(nSample)])
sample_mean
[OUT] :

array([76.35, 69.45, 74.7 , ..., 67.95, 68.15, 71.35])

 

plt.hist(sample_mean, bins=100, range=(0,100),density=True)
plt.xlim(50,90)
# plt.vlines(scores.mean(),0,0.12)
plt.axvline(scores.mean())
plt.show()


review
- 주피터노트북에서 수식 표현하는 방법 : $$사용

 

728x90
반응형
LIST