2017-10-08 1 views
0

플롯의 특정 영역에서 (x, y) 영역을 음영 처리하려고합니다. 단순화 된 예로, 정규 분포를 confidence intervals으로 간주하십시오. 한 표준 편차 (또는 한 시그마) 내의 영역이 가장 어둡고 두 표준 편차 (또는 2 시그마) 내의 영역이 조금 더 가벼워 지도록 신뢰 구간을 음영 처리하고 싶습니다.이 작업을 수행하는 방법이 있습니다. 하지만 스크립트를 좀 더 유연하게 만들려고합니다. 코드는 다음과 같습니다.이 plt.fill_between() 접근법을 루프에서 수정할 수 있습니까?

## imports 
import numpy as np 
import matplotlib.pyplot as plt 
from math import pi 

## y = f(x) 
def get_f(x, mu, sigma): 
    """ Normal Distribution Probability Density Function """ 
    norm_constant = (sigma* (2*pi)**(1/2)) 
    return [norm_constant * np.exp((-1) * (x[idx] - mu)**2/(2* sigma**2)) for idx in range(len(x))] 

x = np.linspace(0, 100, 5000) 

x와 f (x) 함수가 생겼으므로 이제 플롯을 만들 수 있습니다. 나는 작동하는 코드의 일부로 떠났고 해결책에 대한 나의 시도를 주석 처리했다. 원하는 간격의 수를 기반으로 음영이 더 편리하고 코드가 반복적이지 않으므로 솔루션 방법을 사용하는 것이 더 좋습니다.

## generate plot 
def get_plot(x, num_intervals=None, line_color='g', shade_color='b', mu=48, sigma=7): 
    """ Returns (x,y) plot; confidence intervals shading is optional """ 
    y = get_f(x, mu, sigma) 
    plt.plot(x, y, line_color) 
    if num_intervals is not None: 

     ## THIS CODE SEGMENT BELOW WORKS BUT I WOULD LIKE TO MAKE IT BETTER 

     plt.fill_between(x, y, where=(mu - sigma <= x), alpha=0.18, color=shade_color) 
     plt.fill_between(x, y, where=(x <= mu + sigma), alpha=0.18, color=shade_color) 
     plt.fill_between(x, y, where=(mu - 2*sigma <= x), alpha=0.11, color=shade_color) 
     plt.fill_between(x, y, where=(x <= mu + 2*sigma), alpha=0.11, color=shade_color) 
     plt.fill_between(x, y, where=(mu - 3*sigma <= x), alpha=0.02, color=shade_color) 
     plt.fill_between(x, y, where=(x <= mu + 3*sigma), alpha=0.02, color=shade_color) 

     ## THIS CODE SEGMENT BELOW DOES NOT WORK AS I WOULD LIKE 
     ## IT WILL SHADE THE REGIONS IN THE WRONG SHADE/DARKNESS 

     ## choose shading level via dictionary 
     # alpha_keys = [idx+1 for idx in range(num_intervals)] 
     # alpha_vals = [0.18, 0.11, 0.02] 
     # alpha_dict = dict(zip(alpha_keys, alpha_vals)) 
     # for idx in range(num_intervals): 
      # print("\nidx & stdev = %d & %d, \nmu - (stdev * sigma) = %.2f, \nmu + (stdev * sigma) = %.2f, alpha = %.2f" %(idx, stdev, mu - stdev*sigma, mu + stdev*sigma, alpha_dict[stdev]), "\n") 
      # stdev = idx + 1 ## number of standard deviations away from mu 
      # plt.fill_between(x, y, where=(mu - stdev * sigma <= x), alpha=alpha_dict[stdev], color=shade_color) 
      # plt.fill_between(x, y, where=(x >= mu + stdev * sigma), alpha=alpha_dict[stdev], color=shade_color) 


    plt.show() 

올바른 코드를 실행하면 this plot가 생성됩니다. 좀 더 편리한 해결책을 찾으려 할 때 this plot을 생성하고 아래에 출력을 출력합니다 (print 문을 통해). 실수의 원인을 찾을 수는 없습니다.

idx & stdev = 0 & 1, 
mu - (stdev * sigma) = 41.00, 
mu + (stdev * sigma) = 55.00, alpha = 0.18 


idx & stdev = 1 & 2, 
mu - (stdev * sigma) = 34.00, 
mu + (stdev * sigma) = 62.00, alpha = 0.11 


idx & stdev = 2 & 3, 
mu - (stdev * sigma) = 27.00, 
mu + (stdev * sigma) = 69.00, alpha = 0.02 

좀 더 편리한 솔루션을 사용하기에 적합한 방법은 있습니까?

답변

2

여기서는 자신보다 더 작은 일반 분포도를 제공합니다. 휠을 재발 명하기보다는 Scipy 패키지의 정규 분포 함수를 사용합니다.

from scipy.stats import norm # import normal dist. 
import matplotlib.pyplot as plt 
import numpy as np 

# mean and standard deviation 
mu,sigma = 48,7 

# normal_dist(mu,sigma) 
anorm = norm(loc=mu, scale=sigma) 
factors = [1,2,3]   # multiple of sigma 
alphas = [0.18, 0.11, 0.08] # level of alpha 

fig, ax = plt.subplots(1, 1) 
fig.set_size_inches(10,8) 

# plot full normal curve 
segs = 100 
x = np.linspace(anorm.ppf(0.0005), anorm.ppf(0.9995), segs) 
ax.plot(x, anorm.pdf(x), 'b-', lw=0.5, alpha=0.6) 

# plot color-filled portions 
for fac, alp in zip(factors, alphas): 
    # print(mu-fac*sigma, mu+fac*sigma, alp) 
    lo = mu-fac*sigma 
    hi = mu+fac*sigma 
    xs = np.linspace(lo, hi, fac*segs/4) # prep array of x's 
    plt.fill_between(xs, anorm.pdf(xs), y2=0, where= xs >= lo , \ 
        interpolate=False, \ 
        color='blue', alpha=alp) 

plt.ylim(0, 0.06) 

plt.show() 

얻어진 플롯 :

enter image description here

관련 문제