基于日期区间匹配DataFrame 为pandas数据表新增员工所属团队列
实现方案
核心逻辑是匹配同姓名下,工作记录日期落在团队任职开始和结束日期区间内的对应团队,以下是可直接运行的实现代码:
第一步:导入依赖与数据预处理
首先统一将两个表的日期字段转为pandas datetime格式,避免字符串比较出错:
import pandas as pd # 测试数据 dfNotes = pd.DataFrame({ 'Date':'6/30/2021 7/11/2021 7/12/2021 7/13/2021 7/14/2021 7/15/2021'.split(), 'Name': 'Emp1 Emp2 Emp3 Emp1 Emp2 Emp3'.split(), 'Case Notes':'19281080 19356855 19454005 19289960 19206939 19472141'.split() }) dfTeams = pd.DataFrame({ 'Name': 'Emp1 Emp1 Emp1 Emp2 Emp2 Emp2 Emp3 Emp3 Emp3'.split(), 'Team': '2 3 1 1 1 5 1 2 1'.split(), 'Team Start Date': '7/5/2020 4/12/2021 4/28/2021 1/1/2020 3/22/2021 6/4/2021 3/9/2020 11/25/2020 11/30/2020'.split(), 'Team End Date': '4/11/2021 4/27/2021 12/31/2021 3/21/2021 6/3/2021 12/31/2021 11/24/2020 11/29/2021 12/31/2021'.split() }) # 转换日期格式 dfNotes['Date'] = pd.to_datetime(dfNotes['Date']) dfTeams['Team Start Date'] = pd.to_datetime(dfTeams['Team Start Date']) dfTeams['Team End Date'] = pd.to_datetime(dfTeams['Team End Date'])
第二步:匹配团队(两种方案可选)
方案1:小数据量直接关联过滤
实现门槛最低,适合万级以下的数据量:
# 按姓名关联两张表 df_merged = dfNotes.merge(dfTeams, on='Name', how='left') # 筛选符合任职日期区间的记录 df_result = df_merged[(df_merged['Date'] >= df_merged['Team Start Date']) & (df_merged['Date'] <= df_merged['Team End Date'])] # 处理重叠任职区间的情况,保留第一条匹配结果(可根据需求调整规则) df_result = df_result.drop_duplicates(subset=['Date', 'Name', 'Case Notes'], keep='first') # 清理多余字段 df_result = df_result.drop(columns=['Team Start Date', 'Team End Date'])
匹配结果如下:
| Date | Name | Case Notes | Team |
|---|---|---|---|
| 2021-06-30 | Emp1 | 19281080 | 1 |
| 2021-07-11 | Emp2 | 19356855 | 5 |
| 2021-07-12 | Emp3 | 19454005 | 2 |
| 2021-07-13 | Emp1 | 19289960 | 1 |
| 2021-07-14 | Emp2 | 19206939 | 5 |
| 2021-07-15 | Emp3 | 19472141 | 2 |
方案2:大数据量用IntervalIndex优化性能
如果数据量达到十万级以上,方案1的关联会产生大量冗余中间行,该方案通过时间区间索引匹配,内存占用更低、速度更快:
def match_team(row): # 取当前员工的所有任职记录 emp_teams = dfTeams[dfTeams['Name'] == row['Name']] # 生成时间区间索引 intervals = pd.IntervalIndex.from_arrays(emp_teams['Team Start Date'], emp_teams['Team End Date'], closed='both') # 匹配符合条件的团队 match_res = emp_teams.loc[intervals.contains(row['Date']), 'Team'] return match_res.iloc[0] if not match_res.empty else None # 执行匹配 dfNotes['Team'] = dfNotes.apply(match_team, axis=1)
内容的提问来源于stack exchange,提问作者Joseph Savoie
相关产品推荐
相关产品推荐

