Дисплей для заданной гистограммы c (ненормально) - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь наложить усеченное нормальное распределение с указанными параметрами c a и b на гистограмму выборок, сгенерированных из того же самого распределения.

Как мне соответствовать pdf truncnorm (a , б)? This is what it looks like right now

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import matplotlib.mlab as mlab

from IPython.display import Math, Latex
# for displaying images
from IPython.core.display import Image
# import seaborn
import seaborn as sns
# settings for seaborn plotting style
sns.set()
# settings for seaborn plot sizes
sns.set(rc={'figure.figsize':(5,5)})

tempdist=[]

samples=100

for k in range(1,samples):
    #Probability
    #Storage temp as truncated normal
    #temperature as normal mean 55 with 5F variation
    storagetempfarenht = 57 #55
    storagetempkelvin = (storagetempfarenht + 459.67) * (5.0/9.0)
    highesttemp=storagetempfarenht + 5
    lowesttemp= storagetempfarenht -5
    sigma = ((highesttemp + 459.67) * (5.0/9.0)) - storagetempkelvin
    mu, sigma = storagetempkelvin, sigma
    lower, upper = mu-2*sigma , mu+2*sigma
    a=(lower - mu) / sigma
    b=(upper - mu) / sigma
    temp =stats.truncnorm.rvs(a, b, loc=mu, scale=sigma, size=1)
    mean, var, skew, kurt = stats.truncnorm.stats(a, b, moments='mvsk')

    tempdist.append(temp)

#Theses are the randomly generated values
tempdist=np.array(tempdist)

x = range(250,350)

ax = sns.distplot(tempdist,
                  bins=500,
                  kde=True,
                  color='r',
                  fit=stats.truncnorm,
                  hist_kws={"linewidth": 15,'alpha':1})
ax.set(xlabel='Trunc Normal Distribution', ylabel='Frequency')

1 Ответ

0 голосов
/ 14 апреля 2020

Параметр подгонки sns.distplot плохо работает для truncnorm, по крайней мере, с ограниченными данными. truncnorm.fit нужны некоторые догадки, а distplot не знает, как их предоставить.

В этом посте объясняется, как можно вручную установить truncnorm. Код ниже просто dr aws the truncnorm.pdf с начальными параметрами. Чтобы получить подогнанные параметры, вы можете использовать код из связанного поста.

Некоторые замечания:

  • Многие функции numpy (и scipy) работают с полными массивами и могут генерировать полные массивы в одном go. Например, stats.truncnorm.rvs(..., size=N) генерирует массив с N выборками.
  • Установка bins=500 в distplot создаст 500 столбцов гистограммы, что не очень полезно при наличии только 100 выборок.
  • kde=True представляет pdf предполагаемого распределения; по умолчанию это сумма гауссовых ядер; чем больше бинов, тем больше kde следует за деталями данных (вместо их общего вида)
  • Установка "linewidth": 15 в hist_kws создает линии вокруг полос гистограммы шириной 15 пикселей. Это намного шире, чем сами бары, что приводит к странному виду сюжета. Лучше установить ширину линии на 1 или около того.
  • В Python, for k in range(1,samples) запускает образец-1 раз. Это связано с Python начальными индексами массива с 0, а не с 1.
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import matplotlib.mlab as mlab
import seaborn as sns
sns.set()
sns.set(rc={'figure.figsize': (5, 5)})

samples = 100

storagetempfarenht = 57  # 55
storagetempkelvin = (storagetempfarenht + 459.67) * (5.0 / 9.0)
highesttemp = storagetempfarenht + 5
lowesttemp = storagetempfarenht - 5
sigma = ((highesttemp + 459.67) * (5.0 / 9.0)) - storagetempkelvin
mu, sigma = storagetempkelvin, sigma
lower, upper = mu - 2 * sigma, mu + 2 * sigma
a = (lower - mu) / sigma
b = (upper - mu) / sigma
temp = stats.truncnorm.rvs(a, b, loc=mu, scale=sigma, size=1)
# mean, var, skew, kurt = stats.truncnorm.stats(a, b, moments='mvsk')

# Theses are the randomly generated values
tempdist = stats.truncnorm.rvs(a, b, loc=mu, scale=sigma, size=samples)

ax = sns.distplot(tempdist,
                  # bins=10,  # 10 bins is the default
                  kde=True,
                  color='r',
                  # fit=stats.truncnorm, # doesn't work for truncnorm
                  hist_kws={"linewidth": 1, 'alpha': 1, 'label': 'Histogram'},
                  kde_kws={"linewidth": 2, 'alpha': 1, 'color': 'dodgerblue', 'label': 'Estimated kde'})
ax.set(xlabel='Trunc Normal Distribution', ylabel='Frequency')
x_left, x_right = ax.get_xlim()
x = np.linspace(x_left, x_right, 500)
y = stats.truncnorm.pdf(x, a, b, loc=mu, scale=sigma)
ax.plot(x, y, color='limegreen', label='Given truncnormal')
# for xi in (lower, upper):   # optionally draw vertical lines at upper and lower
#    ax.axvline(xi, linestyle=':', color='limegreen')
plt.legend()
plt.tight_layout()
plt.show()

distplot with truncnormal

...