Pandas Dataframe 合并 2 列,包括条件 If 合并:如果 df_2 中的日期在 df_1 中的其他两个日期之间

Posted

技术标签:

【中文标题】Pandas Dataframe 合并 2 列,包括条件 If 合并:如果 df_2 中的日期在 df_1 中的其他两个日期之间【英文标题】:Pandas Dataframe Merge on 2 Columns Including Conditional If Merge: If Date in df_2 is Between Two Other Dates in df_1 【发布时间】:2018-09-09 15:08:46 【问题描述】:

我有以下示例数据框:

df_1:

from datetime import datetime
import pandas as pd

>>> df_1 = pd.DataFrame( 
 "SVDiscrep_Merge": ["2081916SAN", "2081242DFW", "2081248ORD","20874CLE", "2081740DEN"],
 "RON_DATE": [datetime(2017,6,1), datetime(2017,6,4), datetime(2017,6,6), datetime(2017,6,7), datetime(2017,6,8)],
 "Next SV1 Date": [datetime(2017,6,4), datetime(2017,6,6), datetime(2017,6,7), datetime(2017,6,8), datetime(2017, 6, 18)])

>>> df_1

SVDiscrep_Merge     RON_DATE    Next SV1 Date
2081916SAN          6/1/2017    6/4/2017    
2081242DFW          6/4/2017    6/6/2017
2081248ORD          6/6/2017    6/7/2017
20874CLE            6/7/2017    6/8/2017
2081740DEN          6/8/2017    6/18/2017

df_2:

>>> df_2 = pd.DataFrame( 
 "SVDiscrep_Merge": ["2081916SAN", "2081916SAN", "2081916SAN","2081740DEN"],
 "REPORT_DT": [datetime(2017,6,1), datetime(2017,6,3), datetime(2017,6,4), datetime(2017,6,9)],
 "ColA": ["A", "B", "C", "D"])

>>> df_2

SVDiscrep_Merge REPORT_DT   ColA
2081916SAN      6/1/2017    A
2081916SAN      6/3/2017    B
2081916SAN      6/4/2017    C
2081740DEN      6/9/2017    D

我想采用以下逻辑:

    当(且仅当)SVDiscrep_Merge 在两个数据帧中相等时,左合并 df_2df_1

    REPORT_DT 列是 >= RON_DATE 中的日期和 df_1 中 Next SV1 Date 中的日期。

这是我想要的输出:

SVDiscrep_Merge     RON_DATE    Next SV1 Date  ColA 
2081916SAN          6/1/2017    6/4/2017       A    
2081916SAN          6/4/2017    6/6/2017       B
2081916SAN          6/6/2017    6/7/2017
2081242DFW          6/4/2017    6/6/2017    
2081248ORD          6/6/2017    6/7/2017
20874CLE            6/7/2017    6/8/2017
2081740DEN          6/8/2017    6/18/2017      D

如果我没有那个日期逻辑,我知道如何在 python 代码中进行合并......但是有了那个日期逻辑(在搜索 Google 之后)我不知所措。

【问题讨论】:

B 是如何与2081242DFW 排成一行的? 你的数据集是不是太大了,或者我们在谈论一些你不需要超级担心空间的东西? 您确定您的df_2 正确吗? 道歉......你们是对的,我犯了一个错误 【参考方案1】:

您可以在SVDiscrep_Merge 上留下合并,然后使用以下布尔掩码过滤结果:

mask = (((result['RON_DATE'] <= result['REPORT_DT']) 
         & (result['REPORT_DT'] < result['Next SV1 Date'])) 
        | pd.isnull(result['REPORT_DT']))

import datetime as DT 
import pandas as pd

df_1 = pd.DataFrame( 
 "SVDiscrep_Merge": ["2081916SAN", "2081242DFW", "2081248ORD","20874CLE", "2081740DEN"],
 "RON_DATE": [DT.datetime(2017,6,1), DT.datetime(2017,6,4), DT.datetime(2017,6,6), DT.datetime(2017,6,7), DT.datetime(2017,6,8)],
 "Next SV1 Date": [DT.datetime(2017,6,4), DT.datetime(2017,6,6), DT.datetime(2017,6,7), DT.datetime(2017,6,8), DT.datetime(2017, 6, 18)])

df_2 = pd.DataFrame( 
 "SVDiscrep_Merge": ["2081916SAN", "2081916SAN", "2081916SAN","2081740DEN"],
 "REPORT_DT": [DT.datetime(2017,6,1), DT.datetime(2017,6,3), DT.datetime(2017,6,4), DT.datetime(2017,6,9)],
 "ColA": ["A", "B", "C", "D"])

result = pd.merge(df_1, df_2, on='SVDiscrep_Merge',  how='left')
mask = (((result['RON_DATE'] <= result['REPORT_DT']) 
         & (result['REPORT_DT'] < result['Next SV1 Date'])) 
        | pd.isnull(result['REPORT_DT']))
result = result.loc[mask].drop('REPORT_DT', axis=1)
print(result)

产量

  Next SV1 Date   RON_DATE SVDiscrep_Merge ColA
0    2017-06-04 2017-06-01      2081916SAN    A
1    2017-06-04 2017-06-01      2081916SAN    B
3    2017-06-06 2017-06-04      2081242DFW  NaN
4    2017-06-07 2017-06-06      2081248ORD  NaN
5    2017-06-08 2017-06-07        20874CLE  NaN
6    2017-06-18 2017-06-08      2081740DEN    D

这不是您发布的理想结果,但与逻辑描述一致。

【讨论】:

你完全正确!太感谢了;我确实在我想要的输出表中犯了一个错误

以上是关于Pandas Dataframe 合并 2 列,包括条件 If 合并:如果 df_2 中的日期在 df_1 中的其他两个日期之间的主要内容,如果未能解决你的问题,请参考以下文章

将具有相同列/索引的两个 pandas DataFrame 合并为一个 DataFrame

合并具有来自两个不同列的匹配值的 DataFrame - Pandas [重复]

合并 Pandas Dataframe:如何添加列和替换值

pandas读取多个文件内容为dataframe并合并为一个dataframepandas创建仅有列标签而内容为空的dataframe

在 Python 3.x 中将基于特定列的列和值的两个 DataFrame 与 Pandas 合并

pandas将多个Series对象当成数据行进行垂直合并形成dataframepandas将多个Series对象当做数据列垂直合并形成dataframe