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

Python Pandas按活动分组计算距最近活跃状态的累计时间差

问题描述

现有活动日程DataFrame,包含Activity(活动编码)、Status(活动状态,取值Active/Inactive)、Activity Date(活动日期)三个字段,需要按Activity分组,计算每条记录距离同组内最近一次Status=Active记录的累计日期间隔,需覆盖最新活跃日期之后的非活跃状态记录计算。
原始数据集示例:

ActivityStatusActivity Date
1Inactive06/25/22
1Inactive06/21/22
1Active06/19/22
1Inactive06/18/22
2Active05/26/22
2Active05/23/22
2Active05/20/22
2Inactive04/14/22
3Inactive03/05/22
3Inactive02/28/22
3Inactive02/23/22
3Active02/02/22
3Active02/01/22

原有实现的问题:自定义相邻差值计算后按Status分组累计,没有锚定「最近一次Active记录」作为计算基准,无法正确计算非活跃记录间隔。

实现方案

核心思路:先统一日期格式、按时间升序排序,通过merge_asof近似匹配每条记录之前最近的Active记录日期,再计算日期间隔即可,逻辑清晰且不会出现累计错位问题。

完整代码

import pandas as pd

# 1. 构造数据集并转换日期格式
df = pd.DataFrame([
    [1, "Inactive", "06/25/22"],
    [1, "Inactive", "06/21/22"],
    [1, "Active", "06/19/22"],
    [1, "Inactive", "06/18/22"],
    [2, "Active", "05/26/22"],
    [2, "Active", "05/23/22"],
    [2, "Active", "05/20/22"],
    [2, "Inactive", "04/14/22"],
    [3, "Inactive", "03/05/22"],
    [3, "Inactive", "02/28/22"],
    [3, "Inactive", "02/23/22"],
    [3, "Active", "02/02/22"],
    [3, "Active", "02/01/22"]
], columns=["Activity", "Status", "Activity Date"])
# 转换为datetime类型
df["Activity Date"] = pd.to_datetime(df["Activity Date"], format="%m/%d/%y")

# 2. 按活动分组、日期升序排序,保证时间顺序正确
df = df.sort_values(["Activity", "Activity Date"]).reset_index(drop=True)

# 3. 筛选所有Active记录作为匹配表
active_df = df[df["Status"] == "Active"][["Activity", "Activity Date"]].rename(
    columns={"Activity Date": "last_active_date"}
)

# 4. 近似匹配每条记录之前最近的Active日期
df = pd.merge_asof(
    df,
    active_df,
    on="Activity Date",
    by="Activity",
    direction="backward" # 只找当前记录之前的Active
)

# 5. 计算间隔天数:无前置Active记录时差值为0,否则计算当前日期与最近Active日期的天数差
df["Change"] = (df["Activity Date"] - df["last_active_date"]).dt.days
# 处理第一个Active之前的无匹配记录,填充为0
df["Change"] = df["Change"].fillna(0).astype(int)

# 输出结果
print(df[["Activity", "Status", "Activity Date", "Change"]])

逻辑说明

  • 日期格式转换是时间计算的前提,必须先将字符串格式的日期转为pandas内置的datetime类型
  • 排序步骤不可省略,merge_asof依赖有序的时间字段才能正确匹配最近的记录
  • direction="backward"参数保证只会匹配当前记录之前出现的Active记录,不会取未来的活跃日期
  • 无前置Active的记录(即分组内排在第一个Active之前的Inactive记录),last_active_date为空,填充为0即可符合需求
输出结果

运行代码后得到的结果如下,和预期结构一致:

ActivityStatusActivity DateChange
1Inactive2022-06-180
1Active2022-06-190
1Inactive2022-06-212
1Inactive2022-06-256
2Inactive2022-04-140
2Active2022-05-200
2Active2022-05-233
2Active2022-05-266
3Active2022-02-010
3Active2022-02-021
3Inactive2022-02-2321
3Inactive2022-02-2826
3Inactive2022-03-0532

注:如果需要Active记录自身的Change值从1开始计数,只需要在计算Change时对Status为Active的行单独做偏移即可,可根据实际业务规则调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:48:30