Как построить интегральную функцию распределения, взвешенную по значениям (например, сколько людей живет в городах> 1 млн.) - PullRequest
0 голосов
/ 27 марта 2019

У меня есть набор данных с несколькими очень большими наблюдениями, и Меня интересует гистограмма и накопленная функция распределения, взвешенная по самим значениям.

Думайте об этом, как о наличии таблицы, которая показывает жителей для каждого города в регионе / стране. Мне все равно, сколько там городов, меня волнует только то, что, скажем, 20% населения живет в городах с населением менее 10 000 человек , 10% населения живет в крупных городах 1 миллион человек и т. Д.

Matplotlib и seaborn могут рассчитывать взвешенные гистограммы - см. Код ниже.

Моя проблема связана с CDF :

  • numpy.histogram with density = True возвращает значение функции плотности вероятности в ячейках, , поэтому значения не обязательно равны 1
  • matplotlib.pyplot.hist with density = True возвращает значения, сумма которых равна 1, но также отображает гистограмму, в то время как я просто хочу, чтобы значения затем строили линию самостоятельно (линия, а не гистограмма)
  • statsmodels.distributions.empirical_distribution.ECDF не может принимать веса

Я пришел с помощью numpy.histogram, а затем пересчитал себя:

hist_nodens, bin_edges_nodens=np.histogram(d, 100, weights=d, density=False)
hist_nodens /= np.sum(hist_nodens)
sns.lineplot(bin_edges_nodens[1:], np.cumsum(hist_nodens))

Это работает, но мне было интересно, есть ли другие способы? Использование matplotlib.pyplot.hist для создания графика и его закрытия кажется более громоздким.

Я собрал здесь игрушечный пример. Ось у переходит в 1 на графике D, но не в C

import numpy as np
from statsmodels.distributions.empirical_distribution import ECDF
import matplotlib.pyplot as plt
import seaborn as sns

d= np.hstack([\
              np.random.randint(100,1000,4000),
              np.arange(10000,100000,100), \
              np.linspace(200e3,900e3,20), \
              1e6,2e6,4e6
              ])

s=np.sum(d) / 1e6

d /= 1e3

fig,ax=plt.subplots(1,5)

ax[0].set_title('A) Histogram - weighted')
sns.distplot( d, 100,  kde=False, norm_hist=True, ax=ax[0], hist_kws={'weights':d} )

ax[1].set_title('B) Cumulative weighted histogram')
sns.distplot( d, 100, kde=False, norm_hist=True, ax=ax[1], hist_kws={'weights':d,'cumulative':True} )

ax[2].set_title('C) Weighted ECDF \n from np.histogram dens=True')
hist, bin_edges=np.histogram(d, 100, weights=d, density=True)
hist=np.cumsum(hist)
sns.lineplot(bin_edges[1:], hist, ax=ax[2])

ax[3].set_title('D) Weighted ECDF \n from np.histogram dens=False')
hist_nodens, bin_edges_nodens=np.histogram(d, 100, weights=d, density=False)
hist_nodens /= np.sum(hist_nodens)
sns.lineplot(bin_edges_nodens[1:], np.cumsum(hist_nodens), ax=ax[3])

py_n,py_bins,py_patches=plt.hist( d,100, weights=d, density=True, cumulative=True)

ax[4].set_title('E) ECDF - not weighted')
ecdf=ECDF( d  )
x=np.linspace( min(d), max(d), num=1000 )
y=ecdf(x)
ax[4].step(x,y)

1 Ответ

1 голос
/ 30 марта 2019

Ваше решение NumPy хорошее.У matplotlib.pyplot.hist есть несколько других опций, которые могут оказаться полезными.В частности, параметр cumulative = True, чтобы сделать его CDF с histtype = 'step' для создания линейного графика вместо столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...