无需for循环:为DataFrame生成startTime至endTime的日期范围列
矢量化实现日期区间生成方案
方法一:numpy广播+分组映射(纯矢量化,效率最优)
这种方法完全基于numpy和pandas的矢量化操作,彻底避开循环,适合大规模数据场景:
- 先计算每行日期区间的总天数(包含首尾日期):
import pandas as pd import numpy as np # 假设你的数据集存储在df中 df['days_diff'] = (df['endTime'] - df['startTime']).dt.days + 1
- 利用广播机制生成所有日期:
# 重复每行的起始日期,次数等于区间天数 start_dates = np.repeat(df['startTime'].values, df['days_diff']) # 生成每个日期对应的天数偏移量 offsets = np.concatenate([np.arange(n) for n in df['days_diff']]) # 计算完整的日期序列 all_dates = start_dates + np.array(offsets, dtype='timedelta64[D]')
- 映射回原行并聚合为列表:
# 创建分组索引,对应原DataFrame的行号 group_ids = np.repeat(df.index, df['days_diff']) # 按行分组聚合,生成每行的日期列表 date_lists = pd.Series(all_dates, index=group_ids).groupby(level=0).agg(list) # 赋值到新列 df['temp'] = date_lists # 可删除临时列days_diff df.drop('days_diff', axis=1, inplace=True)
方法二:explode反向聚合(易理解,效率达标)
如果觉得纯numpy广播的逻辑绕,也可以用这种更直观的方式,虽然用到apply但后续操作都是矢量化优化的,效率远高于纯for循环:
# 先通过apply生成每行的日期区间序列,再展开 expanded_df = df.assign(temp=df.apply(lambda x: pd.date_range(x['startTime'], x['endTime'], freq='D'), axis=1)).explode('temp') # 按原行索引聚合回列表 df['temp'] = expanded_df.groupby(expanded_df.index)['temp'].agg(list)
结果验证
假设原始数据为:
df = pd.DataFrame({ 'startTime': pd.to_datetime(['2024-01-01', '2024-02-05']), 'endTime': pd.to_datetime(['2024-01-03', '2024-02-07']) })
处理后df['temp']的结果为:
0 [2024-01-01 00:00:00, 2024-01-02 00:00:00, 2024-01-03 00:00:00] 1 [2024-02-05 00:00:00, 2024-02-06 00:00:00, 2024-02-07 00:00:00] Name: temp, dtype: object
内容的提问来源于stack exchange,提问作者Akshay Mitra
相关产品推荐
相关产品推荐

