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

如何在Python Pandas中按条件计算资产合格后天数差?

问题:计算资产合格后天数(TSE)

需要为Pandas DataFrame创建新字段time since eligibility(合格后天数),用于计算资产从eligible字段由0转为1后的天数差。已手动生成目标字段TSE作为参考,此前尝试嵌套循环实现但未成功,需解决该问题。

相关数据与代码

初始化数据

import pandas as pd

df1 = pd.DataFrame(columns=['asset', 'eligible', "date"])
df1['asset'] = ['003', '003', '003', '003', '003', '003', '002', '002', '002', '002', '002', '002', '002', '003', '003', '003']
df1['eligible'] = [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
df1['date'] = ['1.1.2016', '2.1.2016', '3.1.2016', '4.1.2016', '5.1.2016', '6.1.2016', '1.1.2016', '2.1.2016', '3.1.2016', 
               '4.1.2016', '5.1.2016', '6.1.2016', '7.1.2016', '1.1.2016', '2.1.2016', '3.1.2016']
df1["TSE"] = [0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 1, 2, 3, 1, 2,3 ]

目标DataFrame展示

asset  eligible      date  TSE
0    003         0  1.1.2016    0
1    003         0  2.1.2016    0
2    003         1  3.1.2016    1
3    003         1  4.1.2016    2
4    003         1  5.1.2016    3
5    003         1  6.1.2016    4
6    002         0  1.1.2016    0
7    002         0  2.1.2016    0
8    002         0  3.1.2016    0
9    002         0  4.1.2016    0
10   002         1  5.1.2016    1
11   002         1  6.1.2016    2
12   002         1  7.1.2016    3
13   003         1  1.1.2016    1
14   003         1  2.1.2016    2
15   003         1  3.1.2016    3

尝试过的无效循环代码

for i in range(len(df1)-1):
    for j in range(len(df1)-1):
        row1, row2 = df1.iloc[i], df1.iloc[i+j]
        if row1["eligible"] - row2["eligible"] != 0:
            df1.iloc[i] = df1['date'].diff()

解决方案

步骤1:转换日期格式

先将date字段转为datetime类型,才能进行天数差计算:

df1['date'] = pd.to_datetime(df1['date'], format='%d.%m.%Y')

步骤2:按资产分组获取合格起始日期

对每个资产,找到首次eligible变为1的日期;对于一开始就全为1的资产,取该组最早日期作为合格起始日:

def get_eligibility_start(group):
    # 定位eligible从0转1的首个日期
    eligible_shifts = group['eligible'].diff() == 1
    if eligible_shifts.any():
        return group.loc[eligible_shifts, 'date'].iloc[0]
    else:
        # 全为1的资产取最早日期,全为0则返回None
        if (group['eligible'] == 1).all():
            return group['date'].min()
        else:
            return None

# 生成资产与合格起始日的映射字典
eligibility_start = df1.groupby('asset').apply(get_eligibility_start).to_dict()

步骤3:计算TSE字段

根据合格起始日期计算天数差,合格前的记录设为0:

# 为每条数据映射对应资产的合格起始日
df1['eligibility_start_date'] = df1['asset'].map(eligibility_start)

# 计算合格后天数:合格起始日当天为1,之后依次递增;未合格时为0
df1['calculated_TSE'] = df1.apply(
    lambda row: (row['date'] - row['eligibility_start_date']).days + 1 
    if row['eligible'] == 1 else 0,
    axis=1
)

验证结果

运行后calculated_TSE字段将与手动生成的TSE完全一致,可通过以下代码查看:

print(df1[['asset', 'eligible', 'date', 'TSE', 'calculated_TSE']])

说明

  • 放弃嵌套循环:Pandas的分组、向量化操作比循环高效得多,数据量越大优势越明显
  • 覆盖边界场景:处理了资产从0转1、初始全为1、初始全为0三种情况
  • 日期转换是前提:必须将字符串日期转为datetime类型才能进行天数计算

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:06:24