为Pandas数据框按司机分组生成独立的赛季递增顺序列
Pandas数据框按司机分组生成独立的赛季递增顺序列
我明白你想要实现的需求了——给每个司机的参赛赛季按先后顺序分配独立的序号,同一个司机的第一个赛季标1,第二个赛季标2,以此类推,不同司机的赛季序号互不干扰对吧?
先回顾下你的数据:
原始数据框
| performance | driver_id | season |
|---|---|---|
| 1 | 1 | 17 |
| 2 | 1 | 17 |
| 3 | 2 | 17 |
| 4 | 2 | 18 |
| 5 | 2 | 18 |
| 6 | 2 | 19 |
| 7 | 1 | 17 |
| 8 | 1 | 18 |
| 9 | 1 | 18 |
目标数据框
| performance | driver_id | season | season_order |
|---|---|---|---|
| 1 | 1 | 17 | 1 |
| 2 | 1 | 17 | 1 |
| 3 | 2 | 17 | 1 |
| 4 | 2 | 18 | 2 |
| 5 | 2 | 18 | 2 |
| 6 | 2 | 19 | 3 |
| 7 | 1 | 17 | 1 |
| 8 | 1 | 18 | 2 |
| 9 | 1 | 18 | 2 |
你之前尝试的代码是同时按driver_id和season分组后rank,这样其实是在每个司机的同一个赛季组内排序,当然得不到跨赛季的递增序号。我们需要的是仅按driver_id分组,对组内的season值按数值大小分配连续的序号。
这里给你两种简单可行的方法:
方法一:使用groupby + rank(method='dense')
这种方法利用rank的dense参数,确保相同的season值得到相同的序号,且序号是连续递增的:
df['season_order'] = df.groupby('driver_id')['season'].rank(method='dense', ascending=True).astype(int)
method='dense':会给相同的season分配相同的序号,且下一个不同的season序号直接+1(不会跳号)ascending=True:按season的数值从小到大排序分配序号,符合你目标里的逻辑astype(int):把rank得到的浮点数转为整数,和目标格式一致
方法二:使用groupby + factorize
factorize可以把组内的唯一值映射为连续的整数,正好符合我们的需求:
import pandas as pd df['season_order'] = df.groupby('driver_id')['season'].transform( lambda x: pd.factorize(x.sort_values())[0] + 1 )
x.sort_values():先对组内的season排序,确保序号按赛季先后分配pd.factorize()[0]:得到从0开始的连续整数,加1后变成从1开始的序号
这两种方法都能得到你想要的目标数据框,你可以根据自己的习惯选择使用。
备注:内容来源于stack exchange,提问作者Eoin Vaughan
相关产品推荐
相关产品推荐

