如何基于含时间区间的DataFrame批量生成时间序列DataFrame?
解决方案:批量生成时间序列并合并为DataFrame
问题回顾
现有如下DataFrame:
date_start date_end 0 2023-01-01 16:00:00 2023-01-01 17:00:00 1 2023-01-02 16:00:00 2023-01-02 17:00:00 2 2023-01-03 16:00:00 2023-01-03 17:00:00 3 2023-01-04 17:00:00 2023-01-04 19:00:00 4 NaN NaN
需要生成新DataFrame,包含每行date_start到date_end区间内按15分钟间隔的时间值,已知单一行的生成方法,现在要批量处理所有行并合并。
方法一:使用apply逐行生成后拼接
先确保日期列是datetime类型,再定义函数处理每行,最后合并结果:
import pandas as pd # 构造原始DataFrame data = { 'date_start': ['2023-01-01 16:00:00', '2023-01-02 16:00:00', '2023-01-03 16:00:00', '2023-01-04 17:00:00', None], 'date_end': ['2023-01-01 17:00:00', '2023-01-02 17:00:00', '2023-01-03 17:00:00', '2023-01-04 19:00:00', None] } df = pd.DataFrame(data) # 转换为datetime类型,避免类型错误 df['date_start'] = pd.to_datetime(df['date_start']) df['date_end'] = pd.to_datetime(df['date_end']) # 定义生成时间序列的函数,跳过空值行 def get_time_series(row): if pd.isna(row['date_start']) or pd.isna(row['date_end']): return pd.Series(dtype='datetime64[ns]') return pd.Series(pd.date_range(start=row['date_start'], end=row['date_end'], freq='15min')) # 逐行生成,展开并合并为最终DataFrame final_df = df.apply(get_time_series, axis=1).stack().reset_index(drop=True).to_frame(name='datetime')
stack()用于把每行的时间序列展开为单列数据reset_index(drop=True)清理多余的索引,保证结果是连续的单列DataFrame
方法二:用explode实现更简洁的批量处理
先给每行生成时间序列列表,再通过explode展开列表为多行:
import pandas as pd # 构造并转换原始DataFrame(同方法一) data = { 'date_start': ['2023-01-01 16:00:00', '2023-01-02 16:00:00', '2023-01-03 16:00:00', '2023-01-04 17:00:00', None], 'date_end': ['2023-01-01 17:00:00', '2023-01-02 17:00:00', '2023-01-03 17:00:00', '2023-01-04 19:00:00', None] } df = pd.DataFrame(data) df['date_start'] = pd.to_datetime(df['date_start']) df['date_end'] = pd.to_datetime(df['date_end']) # 给每行生成时间序列列表,空行对应空列表 df['time_series'] = df.apply( lambda row: pd.date_range(row['date_start'], row['date_end'], freq='15min').tolist() if not pd.isna(row['date_start']) and not pd.isna(row['date_end']) else [], axis=1 ) # 展开列表并清理列 final_df = df.explode('time_series').drop(columns=['date_start', 'date_end']).rename(columns={'time_series': 'datetime'}) # 过滤掉空行(可选,若不需要保留空值行) final_df = final_df[final_df['datetime'].notna()]
explode会把列表中的每个元素拆分为单独一行,代码更简洁直观- 最后可以根据需求过滤空行,避免无效数据
内容的提问来源于stack exchange,提问作者Pythoneer
相关产品推荐
相关产品推荐

