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

Python Pandas:如何使用date_range向量化函数?

向量化处理Pandas中基于日期区间的展开需求

我明白你想要把每行的START_DATE到STOP_DATE区间展开成连续的日期记录,同时保留对应的KEY和AMOUNT,而且希望用向量化的方式实现,避免低效的循环——这在处理大数据量时尤为关键。下面是两种实用的高效实现方案:

方法一:简洁版(apply + explode,适合中小数据量)

这种写法代码简洁易懂,适合数据规模不大的场景:

import pandas as pd
df = pd.DataFrame({
 'KEY': [1, 2, 3, 1, 1, 2],
 'START_DATE': ['2018-01-05', '2018-01-04', '2018-01-01', '2018-01-23', '2018-02-01', '2018-03-11'],
 'STOP_DATE': ['2018-01-22', '2018-03-10', '2018-01-31', '2018-02-15', '2018-04-01', '2018-07-21'],
 'AMOUNT': [5, 3, 11, 14, 7, 9],
})
df.START_DATE = pd.to_datetime(df.START_DATE, format='%Y-%m-%d')
df.STOP_DATE = pd.to_datetime(df.STOP_DATE, format='%Y-%m-%d')

# 为每行生成日期区间的列表
df['DATE'] = df.apply(lambda row: pd.date_range(row['START_DATE'], row['STOP_DATE'], freq='D'), axis=1)
# 展开日期列表,同时保留其他字段
expanded_df = df.explode('DATE').drop(columns=['START_DATE', 'STOP_DATE'])
# 调整列顺序(可选)
expanded_df = expanded_df[['KEY', 'DATE', 'AMOUNT']]

# 查看结果
print(expanded_df.head())

输出示例:

KEY       DATE  AMOUNT
0    1 2018-01-05       5
1    1 2018-01-06       5
2    1 2018-01-07       5
3    1 2018-01-08       5
4    1 2018-01-09       5

方法二:纯向量化实现(适合大数据量,效率拉满)

如果你的数据规模很大(比如几十万行以上),上面的apply本质还是逐行操作,效率会受限。这种纯向量化的方案完全依赖Pandas的批量操作,速度会快很多:

import pandas as pd
df = pd.DataFrame({
 'KEY': [1, 2, 3, 1, 1, 2],
 'START_DATE': ['2018-01-05', '2018-01-04', '2018-01-01', '2018-01-23', '2018-02-01', '2018-03-11'],
 'STOP_DATE': ['2018-01-22', '2018-03-10', '2018-01-31', '2018-02-15', '2018-04-01', '2018-07-21'],
 'AMOUNT': [5, 3, 11, 14, 7, 9],
})
df.START_DATE = pd.to_datetime(df.START_DATE, format='%Y-%m-%d')
df.STOP_DATE = pd.to_datetime(df.STOP_DATE, format='%Y-%m-%d')

# 计算每个日期区间的天数(+1是因为要包含起始和结束日期)
df['DURATION'] = (df['STOP_DATE'] - df['START_DATE']).dt.days + 1

# 按DURATION的值重复每行,生成基础展开表
expanded_df = df.loc[df.index.repeat(df['DURATION'])].copy()

# 计算每个重复行在原行中的偏移量(从0开始)
expanded_df['OFFSET'] = expanded_df.groupby(expanded_df.index).cumcount()

# 根据偏移量计算对应日期
expanded_df['DATE'] = expanded_df['START_DATE'] + pd.to_timedelta(expanded_df['OFFSET'], unit='D')

# 清理不需要的列并调整顺序
expanded_df = expanded_df.drop(columns=['START_DATE', 'STOP_DATE', 'DURATION', 'OFFSET'])
expanded_df = expanded_df[['KEY', 'DATE', 'AMOUNT']].reset_index(drop=True)

# 查看结果
print(expanded_df.head())

额外说明

  • 如果需要按其他频率(比如周freq='W'、月freq='M')展开,方法一中只需修改pd.date_range的freq参数;方法二中则需要调整DURATION的计算逻辑和timedelta的单位。
  • 两种方法最终的输出结构完全一致,你可以根据自己的数据规模选择合适的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:15:14