我有一个很少有非常大观察值的数据集,我对直方图和由值本身加权的累积分布函数感兴趣。
就像有一张表格可以显示一个地区/国家/地区中每个城市的居民一样。 我不在乎有多少个城镇,我只关心的是,例如,有20%的人口居住在人口少于10,000的城镇,有10%的人口居住在人口众多的大城市超过一百万的人,等等。
Matplotlib和seaborn可以计算加权直方图-请参见下面的代码。
我的问题是CDF :
我想出的是使用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创建一个图,然后关闭它似乎比较麻烦。
我在这里整理了一个玩具示例。在图表D中,y轴变为1,而在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)
答案 0 :(得分:1)
您的NumPy解决方案是一个很好的解决方案。 matplotlib.pyplot.hist还有一些其他选项,您可能会觉得有用。具体来说,使用cumulative = True选项将其设置为带有histtype ='step'的CDF,以创建线图而不是柱线。