Pandas分组对比:检测DataFrame日期间名称组合变化
解决方案
步骤1:提取每个日期的名称组合
首先按日期分组,把每个日期对应的Name列转成不可变集合(frozenset)——我们要比较的是日期对应的名称组合(不关心顺序),而且普通集合不可哈希,没法做后续的比较操作,frozenset刚好能解决这个问题:
# 按Date分组,生成每个日期的名称集合 date_groups = df.groupby('Date')['Name'].apply(lambda x: frozenset(x)).reset_index(name='NameSet')
步骤2:对比相邻日期的组合差异
把分组后的日期按降序排序(和示例数据的顺序对齐),然后用shift()拿到上一个日期的名称集合,通过ne()判断当前日期的组合和上一个是否不同:
- 不同或为首个日期(第一行)就标1
- 相同就标0
# 按日期降序排序,保证相邻对比的是前一个日期 date_groups = date_groups.sort_values('Date', ascending=False).reset_index(drop=True) # 生成Check标记:和上一行组合不同则为1,相同为0 date_groups['Check'] = date_groups['NameSet'].ne(date_groups['NameSet'].shift()).astype(int)
步骤3:把标记映射回原DataFrame
最后通过merge把每个日期对应的Check值批量赋给原表的所有行,确保同一日期的所有行标记一致:
# 合并回原DataFrame df = df.merge(date_groups[['Date', 'Check']], on='Date', how='left')
完整可运行代码
import pandas as pd # 创建示例数据 data = { 'Date': ['2023-10-03', '2023-10-03', '2023-10-02', '2023-10-02', '2023-10-01', '2023-10-01'], 'Name': ['A', 'B', 'A', 'B', 'A', 'C'] } df = pd.DataFrame(data) # 提取每个日期的名称组合 date_groups = df.groupby('Date')['Name'].apply(lambda x: frozenset(x)).reset_index(name='NameSet') # 排序并生成Check标记 date_groups = date_groups.sort_values('Date', ascending=False).reset_index(drop=True) date_groups['Check'] = date_groups['NameSet'].ne(date_groups['NameSet'].shift()).astype(int) # 合并回原表 df = df.merge(date_groups[['Date', 'Check']], on='Date', how='left') print(df)
运行后输出和期望完全一致:
Date Name Check 0 2023-10-03 A 0 1 2023-10-03 B 0 2 2023-10-02 A 1 3 2023-10-02 B 1 4 2023-10-01 A 1 5 2023-10-01 C 1
补充说明
- 如果你的原始数据日期是升序排列,只需要把
sort_values里的ascending=False改成ascending=True即可,逻辑完全通用。 - 用
frozenset是核心细节:普通set不可哈希,无法在shift()后的比较中使用,frozenset作为不可变集合,支持哈希操作,完美适配需求。
内容的提问来源于stack exchange,提问作者jan
相关产品推荐
相关产品推荐

