본문 바로가기
데이터 어쩌구/전처리 및 시각화

[python] 기초 : 통계 시각화

by annmunju 2021. 10. 26.

통계 기초 복습

import numpy as np
import scipy as sp
import seaborn as sns

data = np.array([2,3,3,4,4,4,4,5,5,6])

# 평균
mu = np.sum(data)/len(data) #np.mean(data)

# 분산
sigma2 = np.sum((data - mu)**2)/len(data) #np.var(data)

# 불편분산 : 표본은 분산값이 작아지기 때문에(과소추정) 자유도를 개선함 (N-1)
sigma2 = np.sum((data - mu)**2)/(len(data)-1) #np.var(data, ddof=1)

# 표준편차
sigma = np.sqrt(sigma2) #np.std(data, ddof=1)

# 공분산 : 변수가 2개 경우 관계성을 확인하는 통계량. 관계성이 높은 축에 영향을 크게 받을 수 있어서.. 아래 상관계수!
# 피어슨 상관계수 : 공분산/크기로 나눠줌.

# 히스토그램
sns.displot(data, bins=5, color='black', kde=False) #좌측 그래프
sns.displot(data, bins=5, color='black', kde=True) #우측 그래프

# 이 외 비교그래프
#sns.violinplot(x=, y=, data=, color=)
#sns.jointplot(x= , y= , data= , color= )

import numpy as np
import pandas as pd
import scipy as sp
from scipy import stats

from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline

fish_5 = np.array([2,3,4,5,6])

# 비복원추출
#np.random.choice(fish_5, size=1, replace=True) #1개추출
#np.random.choice(fish_5, size=3, replace=True) #3개추출

# 변화 없이 하기위해서 
np.random.seed(13)
data = np.random.choice(fish_5, size=3, replace=True) 
print(data) # [4 2 4]
np.mean(data) # 3.3333333333333335

# 복원추출
np.random.choice(fish_5, size=3, replace=False) #3개추출
# 그래프 그리기 준비

#1) x좌표 데이터 만들기
x = np.arange(1, 7.1, 0.1)

#2) 평균이 4, 표준편차가 0.8인 정규분포를 따르는 난수
stats.norm.pdf(x=x, loc=4, scale=0.8)

#3) 그래프 그리기(정규분포)
plt.plot(x, stats.norm.pdf(x=x, loc=4, scale=0.8), color='black')

* 모집단을 정규분포로 가정해도 좋을까?

 - 충분히 많은 자연상 데이터들을 대부분 정규분포를 따르기 때문에 

   모집단이 정규분포를 따를 것이라고 가정하고 있음. (편리함!)

 

 

 

 

 

표본 통계

import numpy as np
import pandas as pd
import scipy as sp
from scipy import stats

from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline

# 평균 4, 표준편차 0.8인 정규분포를 띠르는 모집자
population = stats.norm(loc=4, scale=0.8)

# 표본 평균을 10000개 얻기
## population.rvs(size=10) : pop~ 변수에 있는 값 10개만 줘바

sample_mean_array = np.zeros(10000)
np.random.seed(13)
for i in range(0,10000):
    sample = population.rvs(size=10)
    sample_mean_array[i] = np.mean(sample)

print(sample_mean_array)

# [4.3976666  4.18857764 3.8425394  ... 4.12495865 4.12127892 4.05054023]

# 평균 : 4와 비슷해!
np.mean(sample_mean_array)
# 표준편차, 분산은 갯수가 작아서...
np.std(sample_mean_array), np.std(sample_mean_array, ddof=1)
## (0.25328735533634056, 0.25330002065401414)

# 디스토그램 그리기
sns.displot(sample_mean_array, color='black', kde=True)

# 샘플사이즈 다양하게 만들기
size_array = np.arange(10,100100,100) #10부터 100단위로 100000까지 나타나게 됨.
sample_mean_array_size = np.zeros(len(size_array))

for i in range(0, len(size_array)):
    sample = population.rvs(size=size_array[i])
    sample_mean_array_size[i] = np.mean(sample)
    
plt.plot(size_array, sample_mean_array_size, color = 'black', lw=0.3)
plt.hlines(4, 0, 100000, colors='red', linestyles='dashed', lw=5) 
plt.xlabel('sample size')
plt.ylabel('sample mean')
plt.show()

# 평균을 계산하는 함수
def calc_sample_mean(size, n_trial):
    sample_mean_array = np.zeros(n_trial)

    for i in range(0, n_trial):
        sample = population.rvs(size=size)
        sample_mean_array[i] = np.mean(sample)

    return(sample_mean_array)
    
# 다양한 샘플 사이즈 준비
size_array = np.arange(2, 102, 2)

# 샘플 사이즈별로 표준편차 계산
sample_mean_std_array = np.zeros(len(size_array))
np.random.seed(13)

for i in range(0, len(size_array)): 
    sample_mean = calc_sample_mean(size=size_array[i], n_trial=100)
    sample_mean_std_array[i] = np.std(sample_mean, ddof=1)
    
plt.plot(size_array, sample_mean_std_array, color='black')
plt.xlabel("sample size")
plt.ylabel("mean_std value")

# 표준오차
SE = 0.8/np.sqrt(size_array)

plt.plot(size_array, sample_mean_std_array, color='black')
plt.plot(size_array, SE, color='red', ls='dotted')
# 표본분산의 평균값은 모분산과 차이가 있다.
sample_var_array = np.zeros(10000)
np.random.seed(13)
for i in range(0,10000):
    sample = population.rvs(size=10)
    sample_var_array[i] = np.var(sample, ddof=0)

np.mean(sample_var_array) #0.64와 다른 값 : 0.5792337629333761

# 불편분산으로 동일하게 계산
unbios_var_array = np.zeros(10000)
np.random.seed(13)
for i in range(0,10000):
    sample = population.rvs(size=10)
    unbios_var_array[i] = np.var(sample, ddof=1) #불편분산!

np.mean(unbios_var_array) #0.64와 거의 비슷한 값 : 0.6435930699259735

# 다양한 크기 샘플 준비
size_array = np.arange(10, 100100, 100)

# 불편분산을 사이즈별로 구하고
unbios_var_array = np.zeros(len(size_array))
np.random.seed(13)

for i in range(0, len(size_array)): 
    sample = population.rvs(size=size_array[i])
    unbios_var_array[i] = np.var(sample, ddof=1)

unbios_var_array # array([0.47982657, 0.54672273, 0.57905633, ..., 0.63441806, 0.63886466, 0.64194483])

plt.plot(size_array, unbios_var_array, color = 'black', lw=0.4)
plt.hlines(0.64, 0, 100000, colors='red', linestyles='dashed', lw=5) 
plt.xlabel('sample size')
plt.ylabel('unbios_var')
plt.show()

 


정규분포

import numpy as np
import pandas as pd
import scipy as sp
from scipy import stats

from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline

# 정규분포의 확률밀도 함수 : 평균과 분산만 알면 모양이 결정된다.
sigma = 0.8 # 표준편차
mu = 4 # 평균
x=3 # 구하고자하는 x값

1 / (np.sqrt(2*np.pi*sigma**2))*np.exp( (-(x-mu)**2) / (2*sigma**2) )
# 확률밀도함수 stats 함수
stats.norm.pdf(loc=4, scale=0.8, x=3)
# 변형
norm_dist = stats.norm(loc=4, scale=0.8)
norm_dist.pdf(x=3) # 0.2283113567362774

x_plot = np.arange(1, 7.1, 0.1)
plt.plot(x_plot, stats.norm.pdf(loc=4, scale=0.8, x=x_plot));

# 표본에서 비율 : 어떤 값 이하가 되는 비율을 구하려면 어떤 값 이하가 되는 데이터 수 / 샘플 사이즈
np.random.seed(13)

simulated_sample = stats.norm.rvs(loc=4, scale=0.8, size=100000)

np.sum(simulated_sample <= 3) / len(simulated_sample) #10.565%가 3보다 작은 비율. 10565명이 3보다 작다

x_plot = np.arange(1, 7.1, 0.1)
plt.plot(x_plot, stats.norm.pdf(loc=4, scale=0.8, x=x_plot), color='black')
plt.vlines(x=3, ymin=0, ymax=0.5, ls='dashed')

그래프에서 그은 선 보다 작은경우가 10565명

 

#누적분포함수 (분포함수) = 확률 (면적구하기!!)

stats.norm.cdf(loc=4, scale=0.8, x=3)

#0.10564977366685535
# 퍼센트포인트 : 어떤값 이하가 될 확률은 하측확률, 어떤 확률이 될 기준치를 퍼센트포인트라고 함. 
## 확률변수 x가 N(변수)보다 낮을 확률은 M(하측확률)퍼센트. : M을 고정하고 N을 구하는 경우 N=퍼센트포인트
stats.norm.ppf(loc=4, scale=0.8, q=0.025) #2.4320288123679563
lower = stats.norm.cdf(loc=4, scale=0.8, x=3)
stats.norm.ppf(loc=4, scale=0.8, q=lower) #3

#3.0000000000000004

 

 

 

통계적 추정

import numpy as np
import pandas as pd
import scipy as sp
from scipy import stats

from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline

fish = pd.read_csv('/Users/anmunju/Documents/제로베이스 강의자료/통계/211025 - 통계기초(3)/data/3-7-1-fish_length.csv')['length']

# 점추정
mu = np.mean(fish)
sigma_2 = np.var(fish, ddof = 1)

# 구간추정 (t분포:표본 적어서...)
sigma = np.std(fish, ddof=1)
se = sigma/np.sqrt(len(fish))

stats.t.interval(alpha=0.95, df=len(fish)-1, loc=mu, scale=se)
#(3.597010056835825, 4.777068592173221)

 

728x90