Pandas按ID和日期分组筛选相邻Value差值≤1的连续行并计算均值
完整实现方案
核心逻辑是先按ID+Date分组,给组内连续符合「相邻差值绝对值≤1」条件的行打相同的段标识,再筛选每组最长段计算平均值即可,完整代码如下:
import pandas as pd # 1. 计算组内相邻Value的差值绝对值 df['diff'] = abs(df.groupby(['ID', 'Date'])['Value'].diff()) # 2. 给连续符合条件的行打段标识:组内只要出现差值>1的情况,段号+1 df['block'] = df.groupby(['ID', 'Date'])['diff'].apply(lambda x: (x.fillna(0) > 1).cumsum()) # 3. 统计每个段的长度和平均值 block_info = df.groupby(['ID', 'Date', 'block'])['Value'].agg( block_len = 'size', value_avg = 'mean' ).reset_index() # 4. 按ID+Date分组,取长度最长的段的平均值,多个最长段默认取第一个 result = block_info.sort_values( by = ['ID', 'Date', 'block_len'], ascending = [True, True, False] ).drop_duplicates( subset = ['ID', 'Date'], keep = 'first' )[['ID', 'Date', 'value_avg']].reset_index(drop=True)
逻辑说明
- 你之前的代码问题出在计算累计和
cumsum()时没有限制在ID+Date分组内,会出现跨组的段标识错乱,导致计数错误 - 首行的差值为NaN,我们用
fillna(0)处理,保证首行默认属于第一个有效段 - 如果需要处理多个等长最长段的情况,修改
drop_duplicates的keep参数即可,比如keep='last'取最后一个最长段
测试验证
可以用以下测试数据验证逻辑正确性:
# 测试数据 data = { 'ID': [1,1,1,1,2,2,2], 'Date': ['2024-01-01']*4 + ['2024-01-01']*3, 'Value': [1,2,3,5,4,5,7] } df = pd.DataFrame(data)
运行后得到的result结果为:
| ID | Date | value_avg |
|---|---|---|
| 1 | 2024-01-01 | 2.0 |
| 2 | 2024-01-01 | 4.5 |
符合预期:ID1的最长连续段是[1,2,3]、均值2,ID2的最长连续段是[4,5]、均值4.5。
内容的提问来源于stack exchange,提问作者Milica
相关产品推荐
相关产品推荐

