如何按ID分组并组内按日期排序重组Pandas DataFrame?
问题
我有一个包含id、date、val三列的Pandas DataFrame,存在多个不同的id。希望将同一id的所有行集中在一起,组内按date排序,且id无需进行排序(保持原数据中id首次出现的顺序)。
示例初始化代码:
import pandas as pd df = pd.DataFrame() df['id'] = [10, 2, 3, 10, 10, 2, 2] df['date'] = ['2020-01-01 12:00:00','2020-01-01 12:00:00','2020-01-01 12:00:00','2020-01-01 13:00:00','2020-01-01 14:00:00', '2020-01-01 13:00:00','2020-01-01 14:00:00'] df['val'] = [0, 1, 2,-3, 4, 6,7]
期望输出:
id date val 0 10 2020-01-01 12:00:00 0 1 10 2020-01-01 13:00:00 -3 2 10 2020-01-01 14:00:00 4 3 2 2020-01-01 12:00:00 1 4 2 2020-01-01 13:00:00 6 5 2 2020-01-01 14:00:00 7 6 3 2020-01-01 12:00:00 2
说明:共有三个id(10、2、3),先展示id=10的所有按日期排序的数据,接着是id=2的,以此类推,id保持原数据中的出现顺序,不进行数值排序。
解决方案
要实现同一id行聚集、组内按date排序且保持id原出现顺序的需求,可通过以下两种高效方法完成:
方法1:用factorize生成排序键
pd.factorize会给每个首次出现的id分配递增编码,以此作为第一排序依据,搭配date作为第二排序键:
# 确保date列为datetime类型(必要步骤) df['date'] = pd.to_datetime(df['date']) # 生成id的首次出现顺序编码 df['id_seq'] = pd.factorize(df['id'])[0] # 排序后移除临时列并重置索引 result = df.sort_values(by=['id_seq', 'date']).drop('id_seq', axis=1).reset_index(drop=True)
方法2:分组排序后按原顺序拼接
先获取id在原数据中的唯一出现顺序,再分组排序后按该顺序拼接:
df['date'] = pd.to_datetime(df['date']) # 保留id的原始出现顺序 unique_ids = df['id'].unique() # 分组排序并按顺序拼接 result = pd.concat([df[df['id'] == idx].sort_values('date') for idx in unique_ids]).reset_index(drop=True)
两种方法均能得到符合预期的输出,方法1在处理大数据集时性能更优。
内容的提问来源于stack exchange,提问作者Sadcow
相关产品推荐
相关产品推荐

