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

使用Pandas GroupBy+Apply生成多组日期范围,模拟Prophet功能

问题描述

我想在Pandas DataFrame中为多组数据模拟Prophet的make_future_dataframe()功能。如果只为单列创建日期范围,可以用以下代码:

import pandas as pd
my_dataframe['prediction_range'] = pd.date_range(start=my_dataframe['date_column'].min(),
                                           periods=48,
                                           freq='M')

但我的DataFrame结构如下:

id feature1 feature2 date_column
1     0         4.3    2022-01-01
2     0         3.3    2022-01-01
3     0         2.2    2022-01-01
4     1034      1.11   2022-01-01
5     1090      0.98   2022-01-01
6     1078      0      2022-01-01

我写了下面这个函数:

def generate_date_range(date_column, data):
    dates = pd.date_range(start=data[date_column].unique()[0],
                    periods=48,
                    freq='M')
    return dates

然后执行:

my_dataframe = my_dataframe.groupby('id').apply(generate_date_ranges('date_columns', my_dataframe))

结果报错了:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/anaconda/envs/scoring_env/lib/python3.9/site-packages/pandas/core/groupby/groupby.py", line 1377, in apply
    func = com.is_builtin_func(func)
  File "/anaconda/envs/scoring_env/lib/python3.9/site-packages/pandas/core/common.py", line 615, in is_builtin_func
    return _builtin_table.get(arg, arg)
TypeError: unhashable type: 'DatetimeIndex'

我不确定这个方法对不对,也试过用MultiIndex:

multi_index = pd.MultiIndex.from_product([pd.Index(file['id'].unique()), dates], names=('customer', 'prediction_date'))

之后重新索引并填充NaN,但搞不懂为什么apply的版本不能用。我想要的输出是这样的:

id feature1 feature2 date_column prediction_date
    1     0         4.3    2022-01-01 2022-03-01
    1     0         4.3    2022-01-01 2022-04-01
    1     0         4.3    2022-01-01 2022-05-01
    1     0         4.3    2022-01-01 2022-06-01
--- 生成48个周期为止 --
    2     0         3.3    2022-01-01 2022-03-01
    2     0         3.3    2022-01-01 2022-04-01
    2     0         3.3    2022-01-01 2022-05-01
    2     0         3.3    2022-01-01 2022-06-01
问题分析与解决方法

为什么apply版本报错?

调用apply的逻辑完全错了:generate_date_ranges('date_columns', my_dataframe)是直接执行函数并返回了一个DatetimeIndex对象,但groupby.apply()需要接收的是函数对象,不是函数的执行结果。另外函数名还写错了——定义的是generate_date_range,调用时写成了generate_date_ranges,这两个问题叠加导致了报错。

正确的apply实现方式

调整函数逻辑,让apply能为每个分组自动传入数据:

import pandas as pd

def generate_date_range(group):
    # 获取当前分组的起始日期
    start_date = group['date_column'].iloc[0]
    # 生成48个月的日期范围
    dates = pd.date_range(start=start_date, periods=48, freq='M')
    # 将当前分组的行重复48次,然后绑定预测日期
    expanded_group = pd.concat([group]*48, ignore_index=True)
    expanded_group['prediction_date'] = dates
    return expanded_group

# 分组应用函数后合并结果
result = my_dataframe.groupby('id', group_keys=False).apply(generate_date_range).reset_index(drop=True)

更高效的MultiIndex实现方式

用from_product生成多索引的思路是对的,而且在数据量大时性能比apply更好,步骤如下:

# 获取所有唯一id和生成预测日期范围
unique_ids = my_dataframe['id'].unique()
start_date = my_dataframe['date_column'].min()
prediction_dates = pd.date_range(start=start_date, periods=48, freq='M')

# 生成包含id和预测日期的多索引
multi_index = pd.MultiIndex.from_product([unique_ids, prediction_dates], names=['id', 'prediction_date'])

# 将原数据按id设为索引,再重新索引到多索引上自动扩展行
df_indexed = my_dataframe.set_index('id')
result = df_indexed.reindex(multi_index, level='id').reset_index()

这种方法不需要循环或拼接DataFrame,逻辑更简洁,执行效率更高。

验证输出

两种方法最终都会生成你需要的结果:每个id对应的原始行重复48次,每行对应一个连续的月度预测日期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:20:16