You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按id分组计算symbol字段值变更时的日期差

解决方案:按ID分组计算Symbol变更的日期差

问题分析

你的原始代码未按id分组,导致会跨ID比较symbol;同时仅对比当前行与前一行的symbol,无法实现示例中“从同一ID下前一个symbol组的起始日期计算天数差”的需求。以下是修正后的实现方案:

完整代码实现

import pandas as pd

# 示例数据(可替换为你的实际数据)
data = {
    'id': [1,1,1,2,2,2,2,3,3],
    'date': ['2022-08-26','2022-08-27','2022-08-28','2022-08-26','2022-08-27','2022-08-28','2022-08-29','2022-08-29','2022-08-30'],
    'symbol': ['a','a','a','a','a','a','b','c','b']
}
df = pd.DataFrame(data)

# 转换日期格式为datetime
df['date'] = pd.to_datetime(df['date'])

# 按id分组处理
def compute_datediff(group):
    # 给同一id内连续相同的symbol分配组号
    group['symbol_group'] = (group['symbol'] != group['symbol'].shift()).cumsum()
    # 获取每个symbol组的起始日期
    group_start_dates = group.groupby('symbol_group')['date'].first().reset_index()
    # 合并起始日期到原分组
    group = group.merge(group_start_dates, on='symbol_group', suffixes=('', '_start'))
    # 获取前一个symbol组的起始日期
    group['prev_group_start'] = group['date_start'].shift()
    # 计算datediff:新symbol组则计算天数差,否则为0
    group['datediff'] = group.apply(
        lambda row: (row['date'] - row['prev_group_start']).days if row['symbol_group'] > 1 else 0,
        axis=1
    )
    # 清理临时列
    return group.drop(['symbol_group', 'date_start', 'prev_group_start'], axis=1)

# 应用分组函数并重置索引
df = df.groupby('id').apply(compute_datediff).reset_index(drop=True)
print(df)

代码说明

  1. 按ID分组:确保每个ID内的计算独立,不会跨ID干扰。
  2. 标记连续Symbol组:用(group['symbol'] != group['symbol'].shift()).cumsum()给同一ID内连续相同的symbol生成唯一组号,区分不同的symbol阶段。
  3. 提取组起始日期:获取每个symbol组的第一个日期,用于计算变更时的天数差。
  4. 计算日期差:当进入新的symbol组时,用当前日期减去前一个组的起始日期得到天数差,其余行设为0。

输出结果

id       date symbol  datediff
0   1 2022-08-26      a         0
1   1 2022-08-27      a         0
2   1 2022-08-28      a         0
3   2 2022-08-26      a         0
4   2 2022-08-27      a         0
5   2 2022-08-28      a         0
6   2 2022-08-29      b         3
7   3 2022-08-29      c         0
8   3 2022-08-30      b         1

性能优化版(适合大数据集)

如果你的数据量较大,可避免使用apply提升效率:

import pandas as pd

df['date'] = pd.to_datetime(df['date'])

# 按id标记连续symbol组
df['symbol_group'] = df.groupby('id')['symbol'].apply(lambda x: (x != x.shift()).cumsum())

# 获取每个(id, symbol_group)的起始日期
group_start = df.groupby(['id', 'symbol_group'])['date'].first().rename('prev_start')
df = df.join(group_start, on=['id', 'symbol_group'])

# 按id偏移获取前一个组的起始日期
df['prev_start'] = df.groupby('id')['prev_start'].shift()

# 计算datediff
df['datediff'] = df['date'].sub(df['prev_start']).dt.days.fillna(0).astype(int)

# 清理临时列
df = df.drop('symbol_group', axis=1)
print(df)

内容的提问来源于stack exchange,提问作者Jel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:24:45