具有加权数据的分布型图 (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)
简而言之,当我的数据被加权时,对于分布类型图(直方图或 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)