【问题标题】:How do I combine Pandas dataframes by looking at dates in one dataframe that fall within a date range in another dataframe?如何通过查看一个数据框中的日期在另一个数据框中的日期范围内来组合 Pandas 数据框?
【发布时间】:2016-01-16 22:10:15
【问题描述】:

我有两个包含员工数据的数据框,如下所示。一个数据文件包含员工数据,包括员工生病的日期,另一个数据文件包含员工工作的日期(即显示为日期范围)。 我想通过查看特定员工的“病假日”在“工作范围”中的哪个位置来合并这两个文件(希望在 pandas 中)。例如,在下面的图像/数据中,员工 1 于 2015 年 11 月 25 日、2015 年 12 月 23 日和 2015 年 12 月 10 日生病。这些分别属于“工作范围”11/21/2015 - 11/29/2015、12/21/2015 - 12/29/2015 和 10/9/2015 - 10/17/2015。

员工工作日期数据:

╔══════════╦════════════╦════════════╗
║ Employee ║   datein   ║  dateout   ║
╠══════════╬════════════╬════════════╣
║        1 ║ 11/21/2015 ║ 11/29/2015 ║
║        2 ║ 12/9/2015  ║ 12/14/2015 ║
║        3 ║ 11/10/2015 ║ 11/19/2015 ║
║        4 ║ 11/11/2015 ║ 11/17/2015 ║
║        5 ║ 11/30/2015 ║ 12/8/2015  ║
║        1 ║ 12/21/2015 ║ 12/29/2015 ║
║        2 ║ 1/7/2016   ║ 1/12/2016  ║
║        3 ║ 12/10/2015 ║ 12/19/2015 ║
║        4 ║ 12/10/2015 ║ 12/16/2015 ║
║        5 ║ 12/30/2015 ║ 1/7/2016   ║
║        1 ║ 10/9/2015  ║ 10/17/2015 ║
║        2 ║ 10/27/2015 ║ 11/1/2015  ║
║        3 ║ 9/28/2015  ║ 10/7/2015  ║
║        4 ║ 9/29/2015  ║ 10/5/2015  ║
╚══════════╩════════════╩════════════╝

员工生病日期数据:

╔══════════╦════════════╦═══════════╗
║ Employee ║  sickDate  ║ sickness  ║
╠══════════╬════════════╬═══════════╣
║        1 ║ 11/25/2015 ║ flu       ║
║       10 ║ 11/21/2015 ║ hd        ║
║       21 ║ 9/20/2015  ║ other     ║
║        1 ║ 12/23/2015 ║ other     ║
║        4 ║ 12/13/2015 ║ vacationx ║
║        7 ║ 7/21/2015  ║ cough     ║
║        3 ║ 10/1/2015  ║ rash      ║
║        4 ║ 10/5/2015  ║ other     ║
║        5 ║ 1/7/2016   ║ eyex      ║
║        2 ║ 12/12/2015 ║ tanx      ║
║        1 ║ 10/12/2015 ║ fatiguex  ║
╚══════════╩════════════╩═══════════╝

综合数据:

╔══════════╦════════════╦════════════╦════════════╦═══════════╗
║ Employee ║   datein   ║  dateout   ║  sickDate  ║ sickness  ║
╠══════════╬════════════╬════════════╬════════════╬═══════════╣
║        1 ║ 11/21/2015 ║ 11/29/2015 ║ 11/25/2015 ║ flu       ║
║        2 ║ 12/9/2015  ║ 12/14/2015 ║ 12/12/2015 ║ tanx      ║
║        3 ║ 11/10/2015 ║ 11/19/2015 ║            ║           ║
║        4 ║ 11/11/2015 ║ 11/17/2015 ║            ║           ║
║        5 ║ 11/30/2015 ║ 12/8/2015  ║            ║           ║
║        1 ║ 12/21/2015 ║ 12/29/2015 ║ 12/23/2015 ║ other     ║
║        2 ║ 1/7/2016   ║ 1/12/2016  ║            ║           ║
║        3 ║ 12/10/2015 ║ 12/19/2015 ║            ║           ║
║        4 ║ 12/10/2015 ║ 12/16/2015 ║ 12/13/2015 ║ vacationx ║
║        5 ║ 12/30/2015 ║ 1/7/2016   ║ 1/7/2016   ║ eyex      ║
║        1 ║ 10/9/2015  ║ 10/17/2015 ║ 10/12/2015 ║ fatiguex  ║
║        2 ║ 10/27/2015 ║ 11/1/2015  ║            ║           ║
║        3 ║ 9/28/2015  ║ 10/7/2015  ║ 10/1/2015  ║ rash      ║
║        4 ║ 9/29/2015  ║ 10/5/2015  ║ 10/5/2015  ║ other     ║
╚══════════╩════════════╩════════════╩════════════╩═══════════╝

如何在 pandas 或 python 中做到这一点? (感谢您的帮助!)

【问题讨论】:

    标签: python date pandas


    【解决方案1】:

    您需要将此数据作为 df1 放入pd.DataFrame( ... )set_index('Employee')

    ╔══════════╦════════════╦════════════╗
    ║ Employee ║   datein   ║  dateout   ║
    ╠══════════╬════════════╬════════════╣
    ║        1 ║ 11/21/2015 ║ 11/29/2015 ║
    ║        2 ║ 12/9/2015  ║ 12/14/2015 ║
    ║        3 ║ 11/10/2015 ║ 11/19/2015 ║
    ║        4 ║ 11/11/2015 ║ 11/17/2015 ║
    ║        5 ║ 11/30/2015 ║ 12/8/2015  ║
    ║        1 ║ 12/21/2015 ║ 12/29/2015 ║
    ║        2 ║ 1/7/2016   ║ 1/12/2016  ║
    ║        3 ║ 12/10/2015 ║ 12/19/2015 ║
    ║        4 ║ 12/10/2015 ║ 12/16/2015 ║
    ║        5 ║ 12/30/2015 ║ 1/7/2016   ║
    ║        1 ║ 10/9/2015  ║ 10/17/2015 ║
    ║        2 ║ 10/27/2015 ║ 11/1/2015  ║
    ║        3 ║ 9/28/2015  ║ 10/7/2015  ║
    ║        4 ║ 9/29/2015  ║ 10/5/2015  ║
    ╚══════════╩════════════╩════════════╝

    然后将这些数据作为 df2set_index('Employee')

    放到pd.DataFrame( ... )

    ╔══════════╦════════════╦═══════════╗
    ║ Employee ║  sickDate  ║ sickness  ║
    ╠══════════╬════════════╬═══════════╣
    ║        1 ║ 11/25/2015 ║ flu       ║
    ║       10 ║ 11/21/2015 ║ hd        ║
    ║       21 ║ 9/20/2015  ║ other     ║
    ║        1 ║ 12/23/2015 ║ other     ║
    ║        4 ║ 12/13/2015 ║ vacationx ║
    ║        7 ║ 7/21/2015  ║ cough     ║
    ║        3 ║ 10/1/2015  ║ rash      ║
    ║        4 ║ 10/5/2015  ║ other     ║
    ║        5 ║ 1/7/2016   ║ eyex      ║
    ║        2 ║ 12/12/2015 ║ tanx      ║
    ║        1 ║ 10/12/2015 ║ fatiguex  ║
    ╚══════════╩════════════╩═══════════╝

    最后,df = df1.join(df2).reset_index()

    【讨论】:

    • 对不起,当我将它应用到我的“更大”数据文件时,它不起作用。我已将数据放在 Google 文档上。 2 个标签。 docs.google.com/spreadsheets/d/…
    【解决方案2】:

    考虑一种内部和外部pandas merge 方法。下面假设日期为datetime 格式,可能需要从字符串对象进行转换:

    workdf['datein'] = pd.to_datetime(workdf['datein'])
    workdf['dateout'] = pd.to_datetime(workdf['dateout'])
    sickdf['sickDate'] = pd.to_datetime(sickdf['sickDate'])
    
    # INNER MERGE ON BOTH DFs WHERE SICK DAYS REPEAT FOR MATCHING EMPLOYEE ROW IN WORK DAYS
    mergedf = pd.merge(workdf, sickdf, on='Employee', how="inner")
    
    # OUTER MERGE TO KEEP ALL WORK DAY RECORDS WITH FILTERED SICK DAYS DATA SET
    finaldf = pd.merge(mergedf[(mergedf['sickDate'] - mergedf['datein'] >= 0) &
                               (mergedf['dateout'] - mergedf['sickDate'] >= 0)],
                       workdf, on=['Employee', 'datein', 'dateout'], how="outer")
    
    finaldf = finaldf.sort(['Employee','datein','dateout']).reset_index(drop=True)
    

    结果

    #    Employee     datein      dateout     sickDate   sickness
    #0          1 2015-10-09   2015-10-17   2015-10-12   fatiguex
    #1          1 2015-11-21   2015-11-29   2015-11-25        flu
    #2          1 2015-12-21   2015-12-29   2015-12-23      other
    #3          2 2015-10-27   2015-11-01          NaT        NaN
    #4          2 2015-12-09   2015-12-14   2015-12-12       tanx
    #5          2 2016-01-07   2016-01-12          NaT        NaN
    #6          3 2015-09-28   2015-10-07   2015-10-01       rash
    #7          3 2015-11-10   2015-11-19          NaT        NaN
    #8          3 2015-12-10   2015-12-19          NaT        NaN
    #9          4 2015-09-29   2015-10-05   2015-10-05      other
    #10         4 2015-11-11   2015-11-17          NaT        NaN
    #11         4 2015-12-10   2015-12-16   2015-12-13  vacationx
    #12         5 2015-11-30   2015-12-08          NaT        NaN
    #13         5 2015-12-30   2016-01-07   2016-01-07       eyex  
    

    【讨论】:

    • 对不起,当我将它应用到我的“更大”数据文件时,它不起作用。我已将数据放在 Google 文档上。 2 个标签。 docs.google.com/spreadsheets/d/…
    • 您收到什么错误?什么不工作?请务必调整实际的字段名称。还可以考虑删除 Year、Month、Day、MonthNo 列,因为 pandas 在日期时间字段中保留了这些列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 2019-05-20
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多