我有一个大约 1000 行的数据帧和一个名为 calc_value
的列。大约 10% 的calc_value
值为 0。
我想根据calc_value
为数据帧中的每一行分配一个百分位数。但是,由于不唯一的箱边缘,使用 qcut
会给我一个错误:
df['percentile'] = pd.qcut(df.calc_value, 100, labels=False)
它会抛出此错误:
ValueError: Bin edges must be unique: array([ 0. , 0. , 0. , 0. , 0. ,
0. , 0. , 0. , 0. , 0.00182298,
0.0030689 , 0.00394358, 0.00479595, 0.00547278, 0.0060241 ,
0.0066023 , 0.00712708, 0.00760456, 0.00816327, 0.00862069,
0.00917431, 0.00959605, 0.01010101, 0.01058201, 0.01094173,
0.01136364, 0.01185771, 0.01230635, 0.01282051, 0.01324503,
0.01369863, 0.0140051 , 0.01447252, 0.01489758, 0.01528912,
0.01569299, 0.01612903, 0.01657785, 0.01699717, 0.01750547,
0.017924 , 0.01840491, 0.01889004, 0.0193326 , 0.01984022,
0.0202292 , 0.02076186, 0.02118433, 0.02173913, 0.02217742,
0.02265831, 0.0231333 , 0.02369503, 0.02422837, 0.02482127,
0.02551955, 0.0260492 , 0.02659574, 0.02714932, 0.0276922 ,
0.02816901, 0.02882712, 0.02941176, 0.03020364, 0.0308642 ,
0.03141361, 0.03209368, 0.03278689, 0.03349899, 0.03433476,
0.03508136, 0.03571429, 0.03645665, 0.03703704, 0.03768171,
0.03852266, 0.0392761 , 0.04021883, 0.04130278, 0.04222222,
0.04316547, 0.04416658, 0.04528395, 0.04630852, 0.04761905,
0.04908678, 0.05062638, 0.05230894, 0.05421013, 0.05604617,
0.05833204, 0.06024096, 0.06314209, 0.06598985, 0.06975211,
0.07406687, 0.08098836, 0.08905262, 0.10144029, 0.12169944,
0.48 ])
我不在乎垃圾箱边缘是否唯一,我想继续为每行分配一个相等的百分位数 0
值为零。然后从那里继续,在本例中10
下一个百分位数。
如何忽略此错误并继续?
看起来scipy.stats.rankdata
完全可以做你想要的,包括对平局的良好控制
方法 : str, 可选 用于为并列元素分配等级的方法。选项是"平均"、"最小"、"最大"、"密集"和"序数"。
例如,
from scipy.stats import rankdata
>>> rankdata([0, 2, 3, 2], method='min')
array([ 1., 2., 4., 2.])
因此,在您的情况下,您可以使用
from scipy.stats import rankdata
df['percentile'] = rankdata(df.calc_value.values, method=<whatever you want>) / len(df)
(请注意我们如何除以数据帧的长度)。
pd.qcut() 需要一个 interger 编号作为第二个参数,以便数据行数/int 也是一个整数。 因此,您要么必须添加空行以稍后删除它们,要么通过以下方式找到最接近的整数:
div = 100
while True:
if not 968%div:
break
else:
div -= 1
print div