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

Pandas按id分组后为每组添加下一个工作日的新行

完整解决方案

步骤1:统一列名并转换日期类型

你的初始DataFrame中日期列名为'd',但后续代码和期望结果里用的是'Date',先统一列名,同时将日期列转为Pandas的datetime64类型(方便使用工作日偏移量):

import pandas as pd
from pandas.tseries.offsets import BDay
import datetime

# 初始DataFrame
df = pd.DataFrame(data={
    'd': [datetime.date(2010,12,30), datetime.date(2010,12,31), datetime.date(2010,12,30),datetime.date(2010,12,31)], 
    'id': [1,1,2,2], 
    'val': [10,200, 90,420]
})

# 重命名列并转换日期类型
df = df.rename(columns={'d': 'Date'}).astype({'Date': 'datetime64[ns]'})

步骤2:编写分组添加行的函数

修正你之前的函数错误,逻辑上确保只修改最后一行的日期为下一个工作日,其余列保留(val设为NaN):

def add_next_business_day_row(group):
    # 复制组内最后一行数据,避免修改原数据
    new_row = group.iloc[-1].copy()
    # 计算下一个工作日
    new_row['Date'] = new_row['Date'] + BDay(1)
    # 将val设为缺失值
    new_row['val'] = pd.NA
    # 追加新行到组中
    return pd.concat([group, new_row.to_frame().T], ignore_index=True)

# 分组应用函数并重置索引
result_df = df.groupby('id', group_keys=False).apply(add_next_business_day_row).reset_index(drop=True)

步骤3:查看结果

运行后result_df的输出与期望一致:

Date  id   val
0 2010-12-30   1  10.0
1 2010-12-31   1 200.0
2 2011-01-01   1   NaN
3 2010-12-30   2  90.0
4 2010-12-31   2 420.0
5 2011-01-01   2   NaN

错误原因说明

你之前报错AttributeError: 'DataFrame' object has no attribute 'Date',是因为初始DataFrame的日期列名为'd'而非'Date',代码误用了不存在的列名;同时原函数中x.Date + BDay(1)是对整列日期加偏移,而非取最后一行的日期,逻辑有误。

高效替代方案(避免apply)

如果数据量较大,groupby.apply效率偏低,可改用以下方法:

# 提取每组最后一行,计算下一个工作日
last_rows = df.groupby('id').last().reset_index()
last_rows['Date'] = last_rows['Date'] + BDay(1)
last_rows['val'] = pd.NA

# 合并原数据和新行,按id排序
result_df = pd.concat([df, last_rows], ignore_index=True).sort_values(by=['id', 'Date']).reset_index(drop=True)

该方法效率更高,结果与之前一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:22:36