Подтвердить что ты не робот

Вычислить кумулятивную функцию распределения (CDF) в Python

Как я могу вычислить в python функцию Кумулятивная функция распределения (CDF)?

Я хочу рассчитать его из массива точек, которые у меня есть (дискретное распределение), а не с непрерывными распределениями, которые, например, имеют scipy.

4b9b3361

Ответ 1

(Возможно, что моя интерпретация вопроса неверна. Если вопрос заключается в том, как перейти из дискретного PDF в дискретный CDF, тогда np.cumsum разделенное на подходящую константу, будет делать, если выборки равнорасположены. Если массив не равнораспределенный, тогда np.cumsum массива, умноженного на расстояния между точками.)

Если у вас есть дискретный массив сэмплов, и вы хотите знать CDF сэмпла, то вы можете просто отсортировать массив. Если вы посмотрите на отсортированный результат, вы поймете, что наименьшее значение представляет 0%, а наибольшее значение представляет 100%. Если вы хотите узнать значение в 50% распределения, просто посмотрите на элемент массива, который находится в середине отсортированного массива.

Давайте подробнее рассмотрим это на простом примере:

import matplotlib.pyplot as plt
import numpy as np

# create some randomly ddistributed data:
data = np.random.randn(10000)

# sort the data:
data_sorted = np.sort(data)

# calculate the proportional values of samples
p = 1. * np.arange(len(data)) / (len(data) - 1)

# plot the sorted data:
fig = figure()
ax1 = fig.add_subplot(121)
ax1.plot(p, data_sorted)
ax1.set_xlabel('$p$')
ax1.set_ylabel('$x$')

ax2 = fig.add_subplot(122)
ax2.plot(data_sorted, p)
ax2.set_xlabel('$x$')
ax2.set_ylabel('$p$')

Это дает следующий график, где график с правой стороны является традиционной кумулятивной функцией распределения. Он должен отражать CDF процесса за точками, но, естественно, это не так, пока число точек конечно.

cumulative distribution function

Эту функцию легко инвертировать, и она зависит от вашего приложения, какая форма вам нужна.

Ответ 2

Предполагая, что вы знаете, как распределяются ваши данные (т. Е. Вы знаете pdf ваших данных), Scipy поддерживает дискретные данные при расчете cdf.

import numpy as np
import scipy
import matplotlib.pyplot as plt
import seaborn as sns

x = np.random.randn(10000) # generate samples from normal distribution (discrete data)
norm_cdf = scipy.stats.norm.cdf(x) # calculate the cdf - also discrete

# plot the cdf
sns.lineplot(x=x, y=norm_cdf)
plt.show()

enter image description here

Мы даже можем напечатать первые несколько значений cdf, чтобы показать, что они дискретны

print(norm_cdf[:10])
>>> array([0.39216484, 0.09554546, 0.71268696, 0.5007396 , 0.76484329,
       0.37920836, 0.86010018, 0.9191937 , 0.46374527, 0.4576634 ])

Тот же метод для вычисления cdf также работает для нескольких измерений: мы используем 2d данные ниже, чтобы проиллюстрировать

mu = np.zeros(2) # mean vector
cov = np.array([[1,0.6],[0.6,1]]) # covariance matrix
# generate 2d normally distributed samples using 0 mean and the covariance matrix above
x = np.random.multivariate_normal(mean=mu, cov=cov, size=1000) # 1000 samples
norm_cdf = scipy.stats.norm.cdf(x)
print(norm_cdf.shape)
>>> (1000, 2)

В приведенных выше примерах я знал, что мои данные обычно распределяются, поэтому я использовал scipy.stats.norm() - есть несколько распределений, которые поддерживает scipy. Но опять же, вам нужно знать, как распределяются ваши данные заранее, чтобы использовать такие функции. Если вы не знаете, как распределяются ваши данные, и вы просто используете любое распределение для расчета cdf, скорее всего, вы получите неверные результаты.