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

如何递归遍历DataFrame并计算行值?补全缺失的start与end字段

解决DataFrame中按规则递推计算start和end字段的问题

问题背景

原始DataFrame定义如下:

import pandas as pd

list_columns = ['id','start', 'end', 'duration']
list_data = [
    [1,'2023-01-01', '2023-04-02', 0], 
    [2,'2023-01-10', 0, 2],
    [3,'0', 0, 3],
    [4,'0', 0, 4]
]
df = pd.DataFrame(columns=list_columns, data=list_data)

需求规则:

  • 针对每行数据,若start或end的值为'0'或数字0,则按规则计算填充
  • 若start为待填充状态(0/'0'),则取上一行已确定的end值作为当前行的start
  • 当前行的end值 = 当前行的start + 当前行的duration(duration为天数,需与日期类型匹配)

解决方案

首先统一处理数据类型:将start/end转换为日期类型,把0或'0'替换为NaN(标记为待填充值)。

方法一:迭代遍历(推荐,高效易维护)

迭代是处理这类递推问题最直接高效的方式,逐行计算并填充:

import pandas as pd
from datetime import timedelta

# 1. 初始化并预处理数据
list_columns = ['id','start', 'end', 'duration']
list_data = [
    [1,'2023-01-01', '2023-04-02', 0], 
    [2,'2023-01-10', 0, 2],
    [3,'0', 0, 3],
    [4,'0', 0, 4]
]
df = pd.DataFrame(columns=list_columns, data=list_data)

# 转换日期列,将0/'0'转为NaN
df['start'] = pd.to_datetime(df['start'], errors='coerce')
df['end'] = pd.to_datetime(df['end'], errors='coerce')

# 2. 逐行迭代计算
for idx in range(1, len(df)):
    prev_row = df.iloc[idx-1]
    
    # 填充当前行start
    if pd.isna(df.loc[idx, 'start']):
        df.loc[idx, 'start'] = prev_row['end']
    
    # 填充当前行end
    if pd.isna(df.loc[idx, 'end']):
        df.loc[idx, 'end'] = df.loc[idx, 'start'] + timedelta(days=df.loc[idx, 'duration'])

print(df)

运行结果:

id      start        end  duration
0   1 2023-01-01 2023-04-02         0
1   2 2023-01-10 2023-01-12         2
2   3 2023-01-12 2023-01-15         3
3   4 2023-01-15 2023-01-19         4

方法二:递归遍历实现

递归核心是从当前行向上追溯,确保上一行计算完成后再处理当前行:

import pandas as pd
from datetime import timedelta

# 初始化并预处理数据
list_columns = ['id','start', 'end', 'duration']
list_data = [
    [1,'2023-01-01', '2023-04-02', 0], 
    [2,'2023-01-10', 0, 2],
    [3,'0', 0, 3],
    [4,'0', 0, 4]
]
df = pd.DataFrame(columns=list_columns, data=list_data)
df['start'] = pd.to_datetime(df['start'], errors='coerce')
df['end'] = pd.to_datetime(df['end'], errors='coerce')

def fill_row(idx):
    # 基线条件:第一行无需递归
    if idx == 0:
        return
    
    # 先递归处理上一行,确保数据已填充完成
    fill_row(idx - 1)
    
    prev_row = df.iloc[idx - 1]
    
    # 填充当前行start
    if pd.isna(df.loc[idx, 'start']):
        df.loc[idx, 'start'] = prev_row['end']
    
    # 填充当前行end
    if pd.isna(df.loc[idx, 'end']):
        df.loc[idx, 'end'] = df.loc[idx, 'start'] + timedelta(days=df.loc[idx, 'duration'])

# 从最后一行触发递归填充
fill_row(len(df)-1)
print(df)

运行结果与迭代方法一致。

注意:递归方法在DataFrame行数较多时可能出现栈溢出问题,仅适合小数据集;迭代方法更通用高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:05:06