我在数据框中有一个数字列,我需要根据它的值对该行进行分类。例如,
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'
我如何计算这样的分位数并进行比较?
答案 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