如何在Pandas中无循环按条件为DataFrame新增列?
问题描述
我有两个DataFrame,结构如下:
第一个DataFrame:
Value Date 2010-06-29 3 2010-06-30 1 2010-07-01 5 2010-07-02 4 2010-07-03 9 2010-07-04 7 2010-07-05 2 2010-07-06 3
第二个DataFrame:
Value Date 2010-06-29 6 2010-07-03 1 2010-07-06 4
创建第一个DataFrame的代码:
import pandas as pd df = pd.DataFrame( { 'Date': ['2010-06-29', '2010-06-30', '2010-07-01', '2010-07-02', '2010-07-03', '2010-07-04', '2010-07-05', '2010-07-06'], 'Value': [3, 1, 5, 4, 9, 7, 2, 3] } ) df['Date'] = pd.to_datetime(df['Date']).dt.date df = df.set_index('Date')
创建第二个DataFrame的代码:
df2 = pd.DataFrame( { 'Date': ['2010-06-29', '2010-07-03', '2010-07-06'], 'Value': [6, 1, 4] } ) df2['Date'] = pd.to_datetime(df2['Date']).dt.date df2 = df2.set_index('Date')
我需要在第一个DataFrame中新增一列Value_2,该列每个Date对应的值为第二个DataFrame中等于或早于该Date的最新日期对应的Value值,期望输出如下:
Value Value_2 Date 2010-06-29 3 6 2010-06-30 1 6 2010-07-01 5 6 2010-07-02 4 6 2010-07-03 9 1 2010-07-04 7 1 2010-07-05 2 1 2010-07-06 3 4
要求代码不使用任何for循环,该如何实现?
解决方案
可以使用pandas的merge_asof方法,它专门用于按「最近的不大于匹配键」进行左连接,完全符合需求且无循环:
# 重置索引并将日期转换为datetime类型(merge_asof要求匹配键为有序的datetime) df_reset = df.reset_index().rename(columns={'Date': 'date'}) df_reset['date'] = pd.to_datetime(df_reset['date']) df2_reset = df2.reset_index().rename(columns={'Date': 'date', 'Value': 'Value_2'}) df2_reset['date'] = pd.to_datetime(df2_reset['date']) # 执行匹配:direction='backward'表示取右表中小于等于当前日期的最后一行数据 result = pd.merge_asof(df_reset, df2_reset, on='date', direction='backward') # 恢复原索引结构并调整列顺序 result = result.set_index('date').rename_axis('Date')[['Value', 'Value_2']] print(result)
代码说明:
- 索引与日期转换:
merge_asof要求匹配键是有序的datetime类型,因此先将两个DataFrame的索引转为列,再转换日期格式。 - 匹配逻辑:
direction='backward'参数指定取右表中不大于左表当前日期的最新记录,正好对应需求中的「等于或早于该Date的最新值」。 - 结构恢复:将结果的索引改回原格式,并调整列顺序与期望输出一致。
运行上述代码即可得到目标结果。
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

