基于两列且含日期区间条件的Pandas DataFrame合并方法
这问题我之前也碰到过,刚好有两种常用的解决办法,结合你的示例数据给你详细讲讲:
首先先补一个示例的df_2,方便你理解场景:
from datetime import datetime import pandas as pd df_2 = pd.DataFrame( { "SVDiscrep_Merge": ["2081916SAN", "2081916SAN", "2081242DFW", "2081740DEN", "2081740DEN"], "Event_Date": [datetime(2017,6,2), datetime(2017,6,5), datetime(2017,6,5), datetime(2017,6,10), datetime(2017,6,19)] } )
我们的目标是把df_2中满足同一SVDiscrep_Merge且Event_Date处于df_1的RON_DATE和Next SV1 Date之间的行,和df_1合并。
方法1:用merge_asof(高效,适合大数据量)
merge_asof是Pandas专门为有序匹配设计的工具,效率比交叉连接高很多,适合处理大规模数据。
步骤如下:
- 先对两个DataFrame按
SVDiscrep_Merge和日期列排序(merge_asof要求必须排序) - 执行匹配,再过滤掉超出日期范围的行
代码示例:
# 对df_1和df_2按匹配键和日期排序 df_1_sorted = df_1.sort_values(["SVDiscrep_Merge", "RON_DATE"]) df_2_sorted = df_2.sort_values(["SVDiscrep_Merge", "Event_Date"]) # 用merge_asof匹配:找同一SVDiscrep_Merge下,RON_DATE <= Event_Date的最近行 merged = pd.merge_asof( df_2_sorted, df_1_sorted, by="SVDiscrep_Merge", left_on="Event_Date", right_on="RON_DATE", direction="backward" # 取小于等于Event_Date的最大RON_DATE ) # 过滤掉Event_Date >= Next SV1 Date的行,确保日期在区间内 final_merged = merged[merged["Event_Date"] < merged["Next SV1 Date"]]
运行后你会看到,只有df_2中符合日期区间的行被保留下来:
- 比如
2081916SAN的2017-06-02在2017-06-01到2017-06-04之间,会被保留;而2017-06-05超出了区间,会被过滤掉。
方法2:交叉连接+条件过滤(逻辑直观,适合小数据)
如果你的数据量不大,这种方法更易懂:先把同一SVDiscrep_Merge的所有行配对,再筛选出日期符合条件的。
代码示例:
# 先按SVDiscrep_Merge做内连接,把同组的行全部配对 cross_merged = pd.merge(df_1, df_2, on="SVDiscrep_Merge") # 过滤日期条件:Event_Date在RON_DATE(含)和Next SV1 Date(不含)之间 final_merged = cross_merged[ (cross_merged["Event_Date"] >= cross_merged["RON_DATE"]) & (cross_merged["Event_Date"] < cross_merged["Next SV1 Date"]) ]
这种方法的优点是逻辑一目了然,但如果数据量大,交叉连接会产生大量临时行,效率会低一些。
几个注意点
- 确保所有日期列都是
datetime类型,如果不是,先用pd.to_datetime()转换 - 如果你的业务允许
Event_Date等于Next SV1 Date,把条件中的<改成<=即可 - 使用
merge_asof时,一定要记得先排序,否则匹配结果会出错
内容的提问来源于stack exchange,提问作者PineNuts0
相关产品推荐
相关产品推荐

