如何通过查看属于另一个数据帧的日期范围内的一个数据帧中的日期来组合Pandas数据帧?

时间:2016-01-16 22:10:16

标签: python date pandas

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

员工工作日期数据:

╔══════════╦════════════╦════════════╗
║ 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中做到这一点? (谢谢你的帮助!)

2 个答案:

答案 0 :(得分:0)

您需要将此数据作为 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  ║
╚══════════╩════════════╩════════════╝




然后将此数据作为 df2 pd.DataFrame( ... )

添加到set_index('Employee')



╔══════════╦════════════╦═══════════╗
║ 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()

答案 1 :(得分:0)

考虑内部和外部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