具有加权数据的分布型图 (histogram/kde)

Distribution-type graphs (histogram/kde) with weighted data

简而言之,当我的数据被加权时,对于分布类型图(直方图或 kde)我最好的选择是什么?

df = pd.DataFrame({ 'x':[1,2,3,4], 'wt':[7,5,3,1] })

df.x.plot(kind='hist',weights=df.wt.values)

这很好用,但 seaborn 不接受权重 kwarg,即

sns.distplot( df.x, bins=4,              # doesn't work like this
              weights=df.wt.values )     # or with kde=False added

如果 kde 接受权重就好了,但 pandas 和 seaborn 似乎都不允许。

顺便说一句,我意识到可以扩展数据以伪造权重,这在这里很容易,但对我的权重为数百或数千的真实数据没有多大用处,所以我不想寻找这样的解决方法.

总之,仅此而已。我只是想找出除了基本 pandas 直方图之外我还能用加权数据做什么(如果有的话)。我还没有玩过散景,但也欢迎大家提出散景建议。

您必须了解 seaborn 使用的 matplotlib 绘图函数也 pandas 使用。

documentation 所述,sns.distplot 不接受 weights 参数,但它确实接受 hist_kws 参数,该参数将被发送到底层调用至 plt.hist。因此,这应该做你想做的事:

sns.distplot(df.x, bins=4, hist_kws={'weights':df.wt.values}) 

我通过根据权重对数据点重新采样解决了这个问题。

你可以这样做:

from random import random
from bisect import bisect

def weighted_choice(choices):
    values, weights = zip(*choices)
    total = 0
    cum_weights = []
    for w in weights:
        total += w
        cum_weights.append(total)
    x = random() * total
    i = bisect(cum_weights, x)
    return values[i]

samples = [([5, 0.5], 0.1), ([0, 10], 0.3), ([0, -4], 0.3)]
choices = np.array([weighted_choice(samples) for c in range(1000)])
sns.distributions.kdeplot(choices[:, 0], choices[:, 1], shade=True)