如何移除Pandas中与已有时间区间重叠的DataFrame记录
问题描述
给定两个Pandas DataFrame,结构如下:
import pandas as pd df1 = pd.DataFrame({ 'IN': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01'], 'OUT': ['2023-01-10', '2023-02-10', '2023-03-10', '2023-04-10'], 'Ticker': ['AAPL', 'AAPL', 'GOOG', 'GOOG'] }) df2 = pd.DataFrame({ 'IN': ['2023-01-05', '2023-05-01', '2023-02-05', '2023-05-01'], 'OUT': ['2023-01-15', '2023-05-15', '2023-02-15', '2023-05-15'], 'Ticker': ['AAPL', 'GOOG', 'MSFT', 'XXXX'] })
需求说明
需要移除df2中同时满足以下两个条件的记录:
- 与df1的
Ticker相同 - 时间区间(
IN至OUT)与df1中同Ticker的任意区间存在重叠
举例:df1中第一条AAPL的区间是2023-01-01至2023-01-10,df2中第一条AAPL的区间与其重叠,需要移除;df2中第二条GOOG的区间(2023-05-01至2023-05-15)与df1中所有GOOG的区间无重叠,需保留。
尝试过的错误代码
曾尝试以下代码,但未得到正确结果,且在两个DataFrame行数不同时无法运行:
df1 = df1[~((df1['Ticker'].isin(df2['Ticker'])) & (df1['IN'].between(df2['OUT'], df2['OUT'])))]
错误点说明:
- 逻辑方向错误:代码是过滤df1,但需求是处理df2
- 区间判断逻辑错误:
between的参数使用错误,且未正确判断区间重叠 - 对齐问题:当df1和df2行数不同时,列级别的布尔判断无法正确配对对应Ticker的记录
无迭代的简便实现方法
可以通过合并配对+区间重叠判断的方式实现,无需循环迭代:
步骤1:转换时间列为datetime类型
首先要把字符串格式的IN和OUT转为Pandas的datetime类型,否则无法正确进行时间比较:
df1[['IN', 'OUT']] = df1[['IN', 'OUT']].apply(pd.to_datetime) df2[['IN', 'OUT']] = df2[['IN', 'OUT']].apply(pd.to_datetime)
步骤2:按Ticker合并两个DataFrame
用merge将同Ticker的df1和df2记录配对,保留df2的原始索引以便后续筛选:
merged = df2.reset_index().merge(df1, on='Ticker', suffixes=('_df2', '_df1'))
步骤3:判断区间是否重叠
两个时间区间[start1, end1]和[start2, end2]存在重叠的条件是:start1 < end2 且 start2 < end1。据此筛选出df2中需要移除的记录索引:
overlap_mask = (merged['IN_df2'] < merged['OUT_df1']) & (merged['IN_df1'] < merged['OUT_df2']) # 获取所有需要移除的df2索引 to_remove = merged.loc[overlap_mask, 'index'].unique()
步骤4:过滤df2得到结果
从df2中移除上述索引对应的记录:
df2_filtered = df2.drop(to_remove)
最终结果验证
运行后df2_filtered的内容为:
IN OUT Ticker 1 2023-05-01 2023-05-15 GOOG 2 2023-02-05 2023-02-15 MSFT 3 2023-05-01 2023-05-15 XXXX
符合需求:移除了与df1中AAPL区间重叠的第一条记录,保留了其余符合条件的记录。
内容的提问来源于stack exchange,提问作者Unlimited
相关产品推荐
相关产品推荐

