Python:如何在Pandas中创建加权分位数?

14

我知道如何使用pd.qcut在Pandas中创建简单的分位数。但是在搜索了一番之后,我并没有找到任何方法来创建加权分位数。具体而言,我想创建一个变量,将感兴趣的变量值(从最小到最大)分成等权重的不同区间。目前我的代码如下:

def wtdQuantile(dataframe, var, weight = None, n = 10):
    if weight == None:
        return pd.qcut(dataframe[var], n, labels = False)
    else:
        dataframe.sort_values(var, ascending = True, inplace = True)
        cum_sum = dataframe[weight].cumsum()
        cutoff = max(cum_sum)/n
        quantile = cum_sum/cutoff
        quantile[-1:] -= 1
        return quantile.map(int)

有没有更简单的方式,或者Pandas中我遗漏了什么预构建的东西?

编辑: 根据要求,我提供一些样本数据。在下面的内容中,我试图使用"Weight"作为权重来分箱"Var"变量。使用pd.qcut,我们可以获得每个箱中相同数量的观测值。相反,我想要每个箱中的等权重,或者在这种情况下,尽可能接近等权重。

Weight  Var  pd.qcut(n=5)  Desired_Rslt
   10     1            0              0
   14     2            0              0
   18     3            1              0
   15     4            1              1
   30     5            2              1
   12     6            2              2
   20     7            3              2
   25     8            3              3
   29     9            4              3
   45    10            4              4

2
你能提供一些样本数据、输入和输出,以说明你想要的内容吗? - cs95
2
请在询问 Pandas 相关问题时,始终提供样本数据。 - Gustavo Bezerra
1个回答

16

我不认为这是Pandas内置的功能,但是这里有一个函数可以用几行代码实现你想要的功能:

import numpy as np
import pandas as pd
from pandas._libs.lib import is_integer

def weighted_qcut(values, weights, q, **kwargs):
    'Return weighted quantile cuts from a given series, values.'
    if is_integer(q):
        quantiles = np.linspace(0, 1, q + 1)
    else:
        quantiles = q
    order = weights.iloc[values.argsort()].cumsum()
    bins = pd.cut(order / order.iloc[-1], quantiles, **kwargs)
    return bins.sort_index()

我们可以这样在您的数据上进行测试:

data = pd.DataFrame({
    'var': range(1, 11),
    'weight': [10, 14, 18, 15, 30, 12, 20, 25, 29, 45]
})

data['qcut'] = pd.qcut(data['var'], 5, labels=False)
data['weighted_qcut'] = weighted_qcut(data['var'], data['weight'], 5, labels=False)
print(data)

输出结果与您上面所需的结果匹配:

   var  weight  qcut  weighted_qcut
0    1      10     0              0
1    2      14     0              0
2    3      18     1              0
3    4      15     1              1
4    5      30     2              1
5    6      12     2              2
6    7      20     3              2
7    8      25     3              3
8    9      29     4              3
9   10      45     4              4

1
对于大量的分位数,有时会跳过某些箱子。我有20个箱子覆盖了非常大量的数据集,有时会缺少0.75,有时是0.30等等。我并不完全理解这段代码是如何工作的,你有什么猜测为什么它会跳过一些箱子吗? - Rkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接