我想将数据划分为分位数(更具体地说是分位数(。然而,当在Pandas中使用qcut或在R中使用ntile时,我得到的错误是";仓边缘必须是唯一的";(qcut(或相等的值被分配给不同的五分位数(ntile(。
查看以下数据:[1,8,2,1,8]我希望输出为:
- 1分配到五分之一
- 8人被分配到5分之一
- 2被分配到五等分3
- 1再次被分配到五分之一
- 8再次被分配到5分之一
在这种特殊情况下,1也可以分配给五分位数2,而不是1(取决于定义(。同样重要的是,为同一个五分位数分配相等的值。
你对我如何做到这一点有什么想法吗?
非常感谢您的投入!
要使用的一些数据:
import pandas as pd
df = pd.DataFrame({'Date': ['2011-01-01', '2011-01-02', '2011-01-03','2011-01-01', '2011-01-02',
'2011-01-03','2011-01-01', '2011-01-02', '2011-01-03', '2011-01-01','2011-01-02', '2011-01-03',
'2011-01-01', '2011-01-02', '2011-01-03'], 'Name': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'D', 'D', 'D', 'E', 'E', 'E'],
'Value':[1, 3, 2, 8, 6, 5, 2, 10, 4, 1, 5, 3, 8, 4, 9]})
我在R:中使用的代码
df = df %>% group_by(Date) %>% mutate(Quint = ntile(Value, 5))
这为不同的仓分配了相等的值。
我在Python中使用的代码:
df['Quintiles'] = df.groupby(by=["Date"])['Value'].transform(lambda x: pd.qcut(x, 5, labels=["XS", "S", "M", "L", "XL"]))
这导致仓边缘必须是唯一的错误。
更新
在这种特定情况下,1也可以分配给五分位数2,而不是1(取决于定义(。同样重要的是,为同一个五分位数分配相等的值。
cut_rank = lambda x: pd.cut(x.rank(method='min'), 5, labels=["XS", "S", "M", "L", "XL"])
df['Quintiles'] = df.groupby(by=["Date"])['Value'].transform(cut_rank)
输出:
>>> df[df['Date'] == '2011-01-01']
Date Name Value Quintiles
0 2011-01-01 A 1 XS
3 2011-01-01 B 8 XL
6 2011-01-01 C 2 L
9 2011-01-01 D 1 XS
12 2011-01-01 E 8 XL
>>> df
Date Name Value Quintiles
0 2011-01-01 A 1 XS
1 2011-01-02 A 3 XS
2 2011-01-03 A 2 XS
3 2011-01-01 B 8 XL
4 2011-01-02 B 6 L
5 2011-01-03 B 5 L
6 2011-01-01 C 2 L
7 2011-01-02 C 10 XL
8 2011-01-03 C 4 M
9 2011-01-01 D 1 XS
10 2011-01-02 D 5 M
11 2011-01-03 D 3 S
12 2011-01-01 E 8 XL
13 2011-01-02 E 4 S
14 2011-01-03 E 9 XL
旧答案
在qcut
:之前,您必须在每组上使用rank
和method='first'
qcut_rank = lambda x: pd.qcut(x.rank(method='first'), 5, labels=["XS", "S", "M", "L", "XL"])
df['Quintiles'] = df.groupby(by=["Date"])['Value'].transform(qcut_rank)
输出:
>>> df
Date Name Value Quintiles
0 2011-01-01 A 1 XS
1 2011-01-02 A 3 XS
2 2011-01-03 A 2 XS
3 2011-01-01 B 8 L
4 2011-01-02 B 6 L
5 2011-01-03 B 5 L
6 2011-01-01 C 2 M
7 2011-01-02 C 10 XL
8 2011-01-03 C 4 M
9 2011-01-01 D 1 S
10 2011-01-02 D 5 M
11 2011-01-03 D 3 S
12 2011-01-01 E 8 XL
13 2011-01-02 E 4 S
14 2011-01-03 E 9 XL
所有解释都在这里
这是一个部分答案,因为它着眼于numpy对百分位数插值方法的描述,而不是直接应用于pandas
,但在上面的手册中,您可以看到不连续数据集的百分位数的不同插值选项。
import numpy as np
x = [1, 8, 2, 1, 8]
discontinuous_methods = ['linear',
'lower',
'higher',
'midpoint',
'nearest']
for method in discontinuous_methods:
n = [f'{np.percentile(x, i, interpolation = method):.2f}' for i in [20, 40, 60, 80]]
print(f'{method:8s} - {n[0]:3s}, {n[1]:3s}, {n[2]:3s}, {n[3]:3s}')
linear - 1.00, 1.60, 4.40, 8.00
lower - 1.00, 1.00, 2.00, 8.00
higher - 1.00, 2.00, 8.00, 8.00
midpoint - 1.00, 1.50, 5.00, 8.00
nearest - 1.00, 2.00, 2.00, 8.00