Python 熊猫按多列排序
我试图根据两列对熊猫数据帧进行排序。 我可以根据一列对其进行排名,但如何根据两列对其进行排名?”SaleCount,然后是TotalRevenuePython 熊猫按多列排序,python,python-3.x,pandas,rank,Python,Python 3.x,Pandas,Rank,我试图根据两列对熊猫数据帧进行排序。 我可以根据一列对其进行排名,但如何根据两列对其进行排名?”SaleCount,然后是TotalRevenue import pandas as pd df = pd.DataFrame({'TotalRevenue':[300,9000,1000,750,500,2000,0,600,50,500], 'Date':['2016-12-02' for i in range(10)], 'SaleCount':[10,100,30,35,20
import pandas as pd
df = pd.DataFrame({'TotalRevenue':[300,9000,1000,750,500,2000,0,600,50,500],
'Date':['2016-12-02' for i in range(10)],
'SaleCount':[10,100,30,35,20,100,0,30,2,20],
'shops':['S3','S2','S1','S5','S4','S8','S6','S7','S9','S10']})
df['Rank'] = df.SaleCount.rank(method='dense',ascending = False).astype(int)
#df['Rank'] = df.TotalRevenue.rank(method='dense',ascending = False).astype(int)
df.sort_values(['Rank'], inplace=True)
print(df)
电流输出:
Date SaleCount TotalRevenue shops Rank
1 2016-12-02 100 9000 S2 1
5 2016-12-06 100 2000 S8 1
3 2016-12-04 35 750 S5 2
2 2016-12-03 30 1000 S1 3
7 2016-12-08 30 600 S7 3
9 2016-12-10 20 500 S10 4
4 2016-12-05 20 500 S4 4
0 2016-12-01 10 300 S3 5
8 2016-12-09 2 50 S9 6
6 2016-12-07 0 0 S6 7
我正在尝试生成如下输出:
Date SaleCount TotalRevenue shops Rank
1 2016-12-02 100 9000 S2 1
5 2016-12-02 100 2000 S8 2
3 2016-12-02 35 750 S5 3
2 2016-12-02 30 1000 S1 4
7 2016-12-02 30 600 S7 5
9 2016-12-02 20 500 S10 6
4 2016-12-02 20 500 S4 6
0 2016-12-02 10 300 S3 7
8 2016-12-02 2 50 S9 8
6 2016-12-02 0 0 S6 9
将为iterable的每个唯一元素生成唯一值。我们只需要按照我们想要的顺序排序,然后进行因子分解。为了实现多列,我们将排序结果转换为元组
cols = ['SaleCount', 'TotalRevenue']
tups = df[cols].sort_values(cols, ascending=False).apply(tuple, 1)
f, i = pd.factorize(tups)
factorized = pd.Series(f + 1, tups.index)
df.assign(Rank=factorized)
Date SaleCount TotalRevenue shops Rank
1 2016-12-02 100 9000 S2 1
5 2016-12-02 100 2000 S8 2
3 2016-12-02 35 750 S5 3
2 2016-12-02 30 1000 S1 4
7 2016-12-02 30 600 S7 5
4 2016-12-02 20 500 S4 6
9 2016-12-02 20 500 S10 6
0 2016-12-02 10 300 S3 7
8 2016-12-02 2 50 S9 8
6 2016-12-02 0 0 S6 9
另一种方法是将感兴趣的两列类型转换为
str
,并通过连接它们来组合它们。将这些值转换回数值,以便根据其大小进行区分
在method=densed
中,重复值的等级将保持不变。(此处:6)
由于您希望按降序排列,因此在中指定ascending=False
将使您获得所需的结果
col1 = df["SaleCount"].astype(str)
col2 = df["TotalRevenue"].astype(str)
df['Rank'] = (col1+col2).astype(int).rank(method='dense', ascending=False).astype(int)
df.sort_values('Rank')
(按照Nickil Maveli的回答,对两个(非负)int列进行排名的正确方法是将它们转换为字符串,将它们连接起来并转换回int。)
但是如果您知道TotalRevenue
被限制在某个范围内,那么这里有一个快捷方式,例如0到MAX_REVENUE=100000;直接将它们作为非负整数进行操作:
df['Rank'] = (df['SaleCount']*MAX_REVENUE + df['TotalRevenue']).rank(method='dense', ascending=False).astype(int)
df.sort_values('Rank2')
实现这一点的一般方法是将所需的域分组到一个元组中,无论类型如何
df["Rank"] = df[["SaleCount","TotalRevenue"]].apply(tuple,axis=1)\
.rank(method='dense',ascending=False).astype(int)
df.sort_values("Rank")
TotalRevenue Date SaleCount shops Rank
1 9000 2016-12-02 100 S2 1
5 2000 2016-12-02 100 S8 2
3 750 2016-12-02 35 S5 3
2 1000 2016-12-02 30 S1 4
7 600 2016-12-02 30 S7 5
4 500 2016-12-02 20 S4 6
9 500 2016-12-02 20 S10 6
0 300 2016-12-02 10 S3 7
8 50 2016-12-02 2 S9 8
6 0 2016-12-02 0 S6 9
sort_值
+GroupBy.ngroup
这将给出密集的排名
列应在groupby之前按所需顺序排序。在groupby
中指定sort=False
,则遵循此排序,以便按照组在已排序数据框中出现的顺序标记组
cols = ['SaleCount', 'TotalRevenue']
df['Rank'] = df.sort_values(cols, ascending=False).groupby(cols, sort=False).ngroup() + 1
输出:
print(df.sort_values('Rank'))
TotalRevenue Date SaleCount shops Rank
1 9000 2016-12-02 100 S2 1
5 2000 2016-12-02 100 S8 2
3 750 2016-12-02 35 S5 3
2 1000 2016-12-02 30 S1 4
7 600 2016-12-02 30 S7 5
4 500 2016-12-02 20 S4 6
9 500 2016-12-02 20 S10 6
0 300 2016-12-02 10 S3 7
8 50 2016-12-02 2 S9 8
6 0 2016-12-02 0 S6 9
是的。否则,
rank
将无法根据组的大小分配组。@piRSquared:非常感谢:-)请注意,在不返回astype(int)的情况下将两列(col1+col2
串接在一起是危险的
这将是危险的,因为字符串land排序顺序中的'30'>'100'。这在语法上可能是正确的,但如果您看到排名仍然有效地基于TotalRevenue列。这是因为这两个数字的比例不同,所以它们的总和主要受TotalRevenue的影响,而不受SaleCount的影响。可能在重新加总应该会有帮助。这个解决方案基本上是按照TotalRevenue进行排名。如果我们想按另一列(如本例中的商店)进行分组,该怎么办?