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

按ID分组统计连续零值,标记连续3天及以上零值事件

按ID分组标记连续3天及以上零值的Pandas实现

问题描述

现有如下Pandas DataFrame,需要按id分组,检查amount字段中是否存在至少3个连续零值的日期区间。若存在,需标记该事件(新增threeplus_consecutivedays_zeros_flag字段)并记录事件发生日期(新增flag_date字段)。

原始DataFrame

iddateamount
12023-01-0120
12023-01-020
12023-01-030
12023-01-0410
12023-01-0515
12023-01-060
12023-01-070
12023-01-080
12023-01-090
12023-01-108
22023-01-0125
22023-01-0232
22023-01-030
22023-01-0412
22023-01-050
22023-01-060
22023-01-070
22023-01-0813
22023-01-090
22023-01-1012

目标DataFrame

iddateamountthreeplus_consecutivedays_zeros_flagflag_date
12023-01-01200
12023-01-0200
12023-01-0300
12023-01-04100
12023-01-05150
12023-01-0600
12023-01-0700
12023-01-08012023-01-08
12023-01-09012023-01-08
12023-01-1080
22023-01-01250
22023-01-02320
22023-01-0300
22023-01-04120
22023-01-0500
22023-01-0600
22023-01-07012023-01-07
22023-01-08130
22023-01-0900
22023-01-10120

已尝试统计数组中的连续零值,但不清楚如何结合groupby操作实现需求。


解决方案

通过分组标记连续零值区间,再计算区间长度,最后标记符合条件的区间并设置事件日期,完整代码实现如下:

import pandas as pd

# 构造原始DataFrame
df = pd.DataFrame({
    'id': [1]*10 + [2]*10,
    'date': pd.date_range('2023-01-01', periods=10).tolist()*2,
    'amount': [20,0,0,10,15,0,0,0,0,8,25,32,0,12,0,0,0,13,0,12]
})

# 1. 确保date为datetime类型(若原始数据是字符串格式)
df['date'] = pd.to_datetime(df['date'])

# 2. 按id分组,标记连续零值的区间
df['is_zero'] = df['amount'] == 0
# 为每个连续的零值/非零值区间生成唯一分组key
df['zero_group'] = df.groupby('id')['is_zero'].apply(lambda x: x.ne(x.shift()).cumsum())

# 3. 统计每个区间的长度、是否为零值区间,以及符合条件的事件日期
group_stats = df.groupby(['id', 'zero_group']).agg(
    group_length=('is_zero', 'size'),
    flag_date=('date', lambda x: x.iloc[2] if len(x)>=3 else pd.NaT)
).reset_index()

# 4. 将统计结果合并回原表
df = df.merge(group_stats[['id', 'zero_group', 'group_length', 'flag_date']], 
              on=['id', 'zero_group'], how='left')

# 5. 生成flag字段:仅零值区间且长度≥3时标记为1
df['threeplus_consecutivedays_zeros_flag'] = ((df['is_zero']) & (df['group_length'] >=3)).astype(int)

# 6. 清理临时列,格式化日期字段
df['flag_date'] = df['flag_date'].dt.strftime('%Y-%m-%d').fillna('')
df = df.drop(['is_zero', 'zero_group', 'group_length'], axis=1)

# 输出结果
print(df)

代码解释

  1. 连续区间标记:通过is_zero标记零值行,再用cumsum()为同一id下的连续零值/非零值区间生成唯一分组key,确保区间划分准确。
  2. 区间统计:对每个分组计算长度,当长度≥3时取该区间第3个日期作为事件日期。
  3. 标记与格式化:合并统计结果后生成flag字段,清理临时列并将空日期转为空白字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:47:47