如何在Python中计算连续日期均存在的ID的Value差值
问题
编写Python逻辑,计算同一ID在当前日期(t)与日历上前一日期(t-1)的Value差值,仅保留该ID在t和t-1均有记录的行对;若某ID在t-1有记录但t无记录,对应的t-1行需排除出最终输出DataFrame。
示例输入
| Date | id | Value |
|---|---|---|
| 1/1/2024 | a | 100 |
| 1/2/2024 | a | 101 |
| 1/1/2024 | b | 99 |
| 1/5/2024 | b | 97 |
| 1/6/2024 | b | 98 |
| 1/2/2024 | c | 98 |
| 1/5/2024 | c | 97 |
| 1/5/2024 | a | 97 |
期望输出
| Date | id | Value | Delta |
|---|---|---|---|
| 1/1/2024 | a | 100 | |
| 1/2/2024 | a | 101 | 1 |
| 1/5/2024 | b | 97 | |
| 1/6/2024 | b | 98 | 1 |
解决方案
使用Pandas可以高效实现需求,步骤如下:
1. 数据预处理
将日期列转为可计算的datetime类型,并按ID和日期排序,确保数据顺序正确:
import pandas as pd # 构造示例数据 data = { 'Date': ['1/1/2024', '1/2/2024', '1/1/2024', '1/5/2024', '1/6/2024', '1/2/2024', '1/5/2024', '1/5/2024'], 'id': ['a', 'a', 'b', 'b', 'b', 'c', 'c', 'a'], 'Value': [100, 101, 99, 97, 98, 98, 97, 97] } df = pd.DataFrame(data) # 转换日期格式并排序 df['Date'] = pd.to_datetime(df['Date'], format='%m/%d/%Y') df = df.sort_values(by=['id', 'Date']).reset_index(drop=True)
2. 匹配连续日期记录
计算每个日期的前一天,通过自连接找到同一ID在前一天的记录,筛选出连续两天都有数据的行:
# 生成前一天日期列 df['prev_date'] = df['Date'] - pd.Timedelta(days=1) # 自连接匹配同一ID的前一天记录 merged = df.merge(df, left_on=['id', 'prev_date'], right_on=['id', 'Date'], suffixes=('', '_prev'))
3. 计算差值并整理结果
提取需要的列,计算Delta值,同时补充作为前置记录的行(Delta为空):
# 提取当前记录并计算Delta result = merged[['Date', 'id', 'Value']].copy() result['Delta'] = merged['Value'] - merged['Value_prev'] # 收集并补充前置记录(即连续记录对中的前一天行) prev_records = df[ df[['id', 'Date']].apply(tuple, axis=1).isin(merged[['id', 'Date_prev']].apply(tuple, axis=1)) ].copy() prev_records['Delta'] = '' # 合并并去重,得到最终结果 final_result = pd.concat([prev_records, result]).drop_duplicates() final_result = final_result.sort_values(by=['id', 'Date']).reset_index(drop=True) # 还原日期格式为原样式 final_result['Date'] = final_result['Date'].dt.strftime('%m/%d/%Y')
最终输出
运行代码后,final_result即为符合要求的DataFrame,输出结果与示例期望一致。
内容的提问来源于stack exchange,提问作者Lu_ch10
相关产品推荐
相关产品推荐

