如何用更Pythonic且高效的方法基于日期序列给pandas DataFrame新增列?
基于日期区间快速给DataFrame批量赋值的优化方案
我需要根据另一数据集定义的日期序列,给pd.DataFrame新增一列。目前用循环实现了需求,但想找更Pythonic、运行更快的方法。
示例数据
import numpy as np import pandas as pd np.random.seed(2) df1 = pd.DataFrame({ "start": pd.date_range(start="1/1/2022", end="1/5/2022", freq="D"), "stop": pd.date_range(start="1/2/2022", end="1/6/2022", freq="D"), "seq_id": np.random.choice(["a", "b", "c"], size=5) }) df2 = pd.DataFrame({ "V1": np.random.randint(1, 10, 121), "seq_id": str() }, index=pd.date_range(start="1/1/2022", end="1/6/2022", freq="H"))
当前解决方案(循环实现)
for i in range(len(df1)): df2.loc[df1.start[i]:df1.stop[i], "seq_id"] = df1.seq_id[i]
优化方案(向量化操作,高效简洁)
利用pandas的长格式转换、索引重排和前向填充,避免逐行循环:
# 将df1的start/stop转成长格式,标记每个区间的起始和结束节点 df1_melt = df1.melt(id_vars='seq_id', value_name='time', var_name='type') # 处理结束节点:将stop时间延后1小时(匹配df2的小时粒度),并清空seq_id df1_melt['seq_id'] = np.where(df1_melt['type'] == 'stop', '', df1_melt['seq_id']) # 按时间排序并设置索引 df1_melt = df1_melt.sort_values('time').set_index('time') # 重索引到包含df2所有时间点的索引,前向填充得到每个时间点对应的seq_id df2['seq_id'] = df1_melt['seq_id'].reindex(df2.index.union(df1_melt.index)).ffill().loc[df2.index]
优势说明
- 效率更高:避免了循环的逐行赋值,利用pandas的向量化操作,数据量越大性能提升越明显
- 更Pythonic:用pandas原生的DataFrame操作替代手动循环,代码更简洁易读
内容的提问来源于stack exchange,提问作者Carlos Davila
相关产品推荐
相关产品推荐

