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

Pandas时间序列分组:产品首尾0删除与中间双0替换的实现问题

解决方案

我们可以通过pandas的groupby结合自定义处理函数来实现需求,分两步处理每个产品的时间序列数据:

步骤1:准备示例数据

先构造符合需求的测试数据:

import pandas as pd
import numpy as np

# 构造示例数据
data = {
    'Date': [1,2,3,4,5,6,1,2,3,4,5,6],
    'Id': ['a','a','a','a','a','a','b','b','b','b','b','b'],
    'Units': [0,5,0,0,1,3,4,2,0,4,0,0]
}
df = pd.DataFrame(data)

步骤2:定义分组处理函数

编写一个函数,对每个产品的子数据集依次执行删除首尾0值行和替换连续两个0为np.nan的操作:

def process_product_data(group):
    # 1. 删除首尾位置的0值行
    # 找到第一个非0值的索引
    first_valid_idx = (group['Units'] != 0).idxmax()
    # 找到最后一个非0值的索引(反向查找)
    last_valid_idx = (group['Units'] != 0).iloc[::-1].idxmax()
    # 截取首尾非0之间的有效数据
    trimmed_data = group.loc[first_valid_idx:last_valid_idx].copy()
    
    # 2. 将中间连续出现的两个0替换为np.nan
    # 标记出连续0的位置:当前值为0,且前一个或后一个值也是0
    consecutive_zero_mask = (trimmed_data['Units'] == 0) & (
        (trimmed_data['Units'].shift(1) == 0) | (trimmed_data['Units'].shift(-1) == 0)
    )
    # 替换对应位置为np.nan
    trimmed_data.loc[consecutive_zero_mask, 'Units'] = np.nan
    
    return trimmed_data

步骤3:执行分组处理

用groupby按产品ID分组,应用上面的处理函数:

final_result = df.groupby('Id', group_keys=False).apply(process_product_data)

结果验证

处理后的结果与示例完全匹配:

  • 产品a:保留Date2-6的行,Units列变为5, np.nan, np.nan, 1, 3
  • 产品b:保留Date1-4的行,Units列保持4, 2, 0, 4

关键逻辑说明

  • 首尾0值删除:通过idxmax找到第一个和最后一个非0值的索引,直接截取中间区间,避免循环遍历行。
  • 连续0替换:利用shift()函数判断当前0值的前后是否也是0,精准标记连续出现的0,批量替换为np.nan,效率远高于逐行判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:11:16