Pandas按col1分组、col3排序后检测col2行间变化出错排查
解决DataFrame分组排序后检测相邻行数值变化的错误问题
问题重现
你需要按col1分组、按col3排序,同时检测col2中相邻行的数值变化,但当前代码运行结果不符合预期。
原始代码
import pandas as pd import datetime my_df = pd.DataFrame({'col1': ['a', 'a', 'a', 'b', 'b', 'b'], 'col2': [2, 2, 3, 5, 5, 5], 'col3': [datetime.date(2023, 2, 1), datetime.date(2023, 3, 1), datetime.date(2023, 4, 1), datetime.date(2023, 2, 1), datetime.date(2023, 3, 1), datetime.date(2023, 4, 1)]}) my_df.sort_values(by=['col3'], inplace=True) my_df_temp = my_df.groupby('col1')['col2'].apply( lambda x: x != x.shift(1) ).reset_index(name='col2_change')
原始DataFrame
col1 col2 col3 0 a 2 2023-02-01 1 a 2 2023-03-01 2 a 3 2023-04-01 3 b 5 2023-02-01 4 b 5 2023-03-01 5 b 5 2023-04-01
错误结果
col1 level_1 col2_change 0 a 0 True 1 a 1 False 2 a 2 True 3 b 3 True 4 b 4 False 5 b 5 False
错误原因分析
- 排序逻辑不严谨:仅按
col3全局排序会导致不同col1的行交替出现,虽然组内col3顺序正确,但数据结构不够清晰,也不符合分组后排序的常规逻辑。 - 相邻比较逻辑偏差:每组第一行没有前置行,
x.shift(1)返回NaN,而x != x.shift(1)会将NaN与值的比较结果判定为True,这不符合“无前置行则无变化”的预期。 - 结果格式冗余:
reset_index后生成的level_1列是原DataFrame的索引,属于多余信息,且未将结果与原数据关联,实用性差。
修正方案
优化后的代码
import pandas as pd import datetime my_df = pd.DataFrame({'col1': ['a', 'a', 'a', 'b', 'b', 'b'], 'col2': [2, 2, 3, 5, 5, 5], 'col3': [datetime.date(2023, 2, 1), datetime.date(2023, 3, 1), datetime.date(2023, 4, 1), datetime.date(2023, 2, 1), datetime.date(2023, 3, 1), datetime.date(2023, 4, 1)]}) # 按col1分组、col3排序,确保同组行连续且按时间有序 my_df = my_df.sort_values(by=['col1', 'col3']) # 分组检测col2相邻变化,第一行标记为False(无前置行无变化) my_df['col2_change'] = my_df.groupby('col1')['col2'].apply( lambda x: x.ne(x.shift()).fillna(False) ) print(my_df)
正确结果
col1 col2 col3 col2_change 0 a 2 2023-02-01 False 1 a 2 2023-03-01 False 2 a 3 2023-04-01 True 3 b 5 2023-02-01 False 4 b 5 2023-03-01 False 5 b 5 2023-04-01 False
关键修正点
- 排序优化:按
['col1', 'col3']排序,确保同一分组的行连续排列,符合分组后排序的逻辑。 - 比较逻辑修正:使用
x.ne(x.shift())(等价于x != x.shift())生成变化标记,再用fillna(False)将每组第一行的NaN替换为False,贴合实际需求。 - 结果整合:直接将结果赋值为原DataFrame的新列,避免冗余列,同时保留完整数据上下文。
内容的提问来源于stack exchange,提问作者user1700890
相关产品推荐
相关产品推荐

