Попытка интерполировать вывод функции гистограммы в Python - PullRequest
3 голосов
/ 02 марта 2020

То, что я пытаюсь сделать, - это поиграть с случайным распределением. Я не хочу, чтобы это было нормально. Но пока нормально все проще.

import matplotlib.pyplot as plt
from scipy.stats import norm

ws=norm.rvs(4.0, 1.5, size=100)
density, bins = np.histogram(ws, 50,normed=True, density=True)
unity_density = density / density.sum()

fig, ((ax1, ax2)) = plt.subplots(nrows=1, ncols=2, sharex=True, figsize=(12,6))
widths = bins[:-1] - bins[1:]

ax1.bar(bins[1:], unity_density, width=widths)
ax2.bar(bins[1:], unity_density.cumsum(), width=widths)

fig.tight_layout()

enter image description here Тогда, что я могу сделать, это визуализировать CDF с точки зрения точек.

density1=unity_density.cumsum()
x=bins[:-1]
y=density1

plt.plot(x, density1, 'o')

enter image description here

Итак, я пытался использовать функцию np.interp на выходе np.histogram для получения гладкой кривой, представляющей CDF и извлечение процентных пунктов для их построения. В идеале мне нужно попытаться сделать все это вручную и с помощью функции ppf от scipy. Я всегда боролся со статистикой как студент. Сейчас я учусь в аспирантуре и стараюсь выполнить как можно больше упражнений, чтобы глубже понять происходящее. Я дошел до отчаяния от этой задачи. Спасибо!

1 Ответ

4 голосов
/ 02 марта 2020

Одна возможность получить более гладкие результаты - использовать больше образцов, используя 10^5 samples и 100 bins. Я получаю следующие изображения:

ws = norm.rvs(loc=4.0, scale=1.5, size=100000)
density, bins = np.histogram(ws, bins=100, normed=True, density=True)

histogram histogram

В общем, вы можете использовать scipys модуль интерполяции для сглаживания вашего CDF. Для 100 samples и коэффициента сглаживания s=0.01 я получаю:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import splev, splrep

density1 = unity_density.cumsum()
x = bins[:-1]
y = density1

# Interpolation
spl = splrep(x, y, s=0.01, per=False)
x2 = np.linspace(x[0], x[-1], 200)
y2 = splev(x2, spl)

# Plotting
fig, ax = plt.subplots()
plt.plot(x, density1, 'o')
plt.plot(x2, y2, 'r-')

CDF of Norm(loc=4, scale=1.5) interpolated

Третья возможность состоит в аналитическом вычислении CDF. Если вы генерируете шум самостоятельно с помощью функции numpy / scipy, большую часть времени уже есть доступная реализация CDF, в противном случае вы должны найти ее в Википедии. Если ваши образцы взяты из измерений, это, конечно, другая история.

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

fig, ax = plt.subplots()
x = np.linspace(-2, 10)
y = norm(loc=4.0, scale=1.5).cdf(x)
ax.plot(x, y, 'bo-')

CDF of Norm(loc=4, scale=1.5) analytically

...