熊猫:如何基于扩展分位数来创建类别?

时间:2016-10-28 12:46:50

标签: python pandas quantile

我在数据框中有一个数字列,我需要根据它的值对该行进行分类。例如,

id   value
1    2.0
2    3.0
3    4.5
4    5.5

我需要一个新的类别变量group,它基于该行之前的行的分位数值。因此,对于id=2,它将考虑分位数计算中的第1行和第2行。然后进行分类,如:

if value > quantile(90%)                              category = 'Very High'
if value > quantile(75%) & value <= quantile(90%) &   category = 'High'
if value > quantile(25%) & value <= quantile(75%) &   category = 'Normal'
if value <= quantile(25%)                             category = 'Low'

我如何计算这样的分位数并进行比较?

1 个答案:

答案 0 :(得分:1)

也许我不太了解这个问题,但由于你的系列总是在增加,所以最后一个值的分位数总是1.所以输出应该一直是“非常高”。

这不是超级高效的,因为我正在为每次迭代创建一个系列,但它可以解决问题。你可以用scipy来改变apply函数来计算百分位数,它会加快这个过程

这都是因为DataFrame.expanding()没有rank()方法。如果可能的话,那将是非常直接的。

def ranking(x):
    return pd.Series(x).rank(pct=True).values[-1]

ranked = sx.expanding().apply(lambda x: ranking(x))
pd.cut(ranked, (0, 0.25, 0.75, 0.90, 1), labels=['low', 'Normal', 'High', 'Very High'])
Out[97]: 
0    Very High
1    Very High
2    Very High
3    Very High
dtype: category
Categories (4, object): [low < Normal < High < Very High]

更快的解决方案与scipy依赖:

from scipy.stats import rankdata
ranked = sx.expanding().agg(lambda x: rankdata(x)[-1]/len(x))

In[108]: import timeit
In[109]: %timeit sx.expanding().agg(lambda x: rankdata(x)[-1]/len(x))
1000 loops, best of 3: 611 us per loop
In[110]: %timeit sx.expanding().apply(lambda x: ranking(x))
1000 loops, best of 3: 1.15 ms per loop