我一直在努力寻找解决这个问题的最佳方法 .
为了概括这个问题并帮助其他可能发现自己需要执行类似任务的人,我试图找到将列添加到第三个数据集的最佳方法,即基于中间数据集中的匹配,并且属于第三个数据集的日期范围 . 最终结果是将第三个数据集中的匹配值返回到第一个数据集 .
以下是示例数据框的头部,以增加一些清晰度:
> head(SalesData, 10)
sale_id sale_amt int_rate sale_date sale_status
1 1 7000 10.71 2008-05-01 Fully Paid
2 2 10800 13.57 2009-11-01 Fully Paid
3 3 7500 10.08 2008-04-01 Fully Paid
4 4 3000 14.26 2009-09-01 Fully Paid
5 5 5600 14.96 2010-02-01 Charged Off
6 6 2800 11.49 2010-08-01 Fully Paid
7 7 10000 8.59 2009-10-01 Fully Paid
8 8 18000 10.39 2008-03-01 Fully Paid
9 9 5000 15.13 2008-04-01 Fully Paid
10 10 9600 12.29 2008-03-01 Fully Paid
> head(EmployeeSales, 10)
sale_id empl_name empl_num
1 1 Dakota 4
2 2 Dakota 4
3 3 Kami 9
4 4 Adel 1
5 5 Adel 1
6 6 Farah 6
7 7 Kami 9
8 8 Kami 9
9 9 Ida 7
10 10 Kami 9
> head(EmployeeMap, 10)
empl_num empl_name skill_lvl team start_date end_date
1 1 Adel Beg Red 2007-06-01 2008-05-31
2 1 Adel Int Red 2008-06-01 2010-10-31
3 1 Adel Adv Red 2010-11-01 2999-12-12
4 2 Bailey Beg Blue 2010-08-01 2011-04-30
5 2 Bailey Beg Red 2011-05-01 2999-12-12
6 3 Casey Beg Blue 2010-08-01 2010-12-31
7 3 Casey Int Blue 2011-01-01 2999-12-12
8 4 Dakota Beg Red 2007-06-01 2009-08-30
9 4 Dakota Int Red 2009-09-01 2010-08-30
10 4 Dakota Adv Red 2010-09-01 2011-08-30
所需的输出会将EmployeeMap的empl_num,sales_team和skill_level添加到每个sale_id的SalesData中 .
在尝试概念化步骤时,这就是我的想法,但也许有更好的方法:从SalesData获取sale_id,将其与Employee Sales中的sale_id匹配并获得empl_num . 获取empl_num并将其与Employee Map中的empl_num匹配 . 现在我们需要从SalesData获取sale_date并找到它所属的“start_date,end_date”范围 . 然后我们将获取匹配的团队和技能级别,并将其添加到SalesData .
见下表:
> head(df2,10)
sale_id sale_amt int_rate sale_date sale_status empl_num team skill_lvl
1 1 7000 10.71 2008-05-01 Fully Paid 4 Red Beg
2 2 10800 13.57 2009-11-01 Fully Paid 4 Red Int
3 3 7500 10.08 2008-04-01 Fully Paid 9 Blue Beg
4 4 3000 14.26 2009-09-01 Fully Paid 1 Red Int
5 5 5600 14.96 2010-02-01 Charged Off 1 Red Int
6 6 2800 11.49 2010-08-01 Fully Paid 6 Red Beg
7 7 10000 8.59 2009-10-01 Fully Paid 9 Blue Int
8 8 18000 10.39 2008-03-01 Fully Paid 9 Blue Beg
9 9 5000 15.13 2008-04-01 Fully Paid 7 Blue Beg
10 10 9600 12.29 2008-03-01 Fully Paid 9 Blue Int
让我复杂化的是,在EmployeeMap中,start_date和end_date告诉我们每个员工开始和结束属于特定技能级别和团队的日期 . 但是每个员工都改变了技能水平和/或团队,因此每个员工都有多行 .
例如,在empl_id 1的EmployeeMap中,我们可以看到3行告诉我们他们的start_date和end_date,而他们在Red Team上有一个skill_level Beg,Int,Adv all . 但有些人,比如empl_id 2,在保持相同技能水平的同时改变团队 . 而其他人则会改变技能水平和团队 .
我将非常感谢您对解决此问题的最佳方法的任何见解 .
3 回答
考虑按日期运行
merge
两次然后subset
. 下面将呼叫嵌在一个长的单行中,但可以在单独的行中分开 . 此外,由于您发布的数据是样本行,因此输出小于您想要的结果 .也许最简单的方法是使用两个类似SQL的连接(如果你不熟悉连接/关系代数,我建议你给一些like this读取) .
可以使用基本R中的
merge
函数执行许多连接,并且许多其他流行的包(dplyr
,data.table
,sqldf
,仅举几例)在连接操作中提供替代语法或扩展功能 .您可以使用
merge
轻松完成两个连接中的第一个(SalesData
和_1844207之间):然而,第二次连接更复杂,因为它不是典型的equi-join . 相反,连接逻辑需要在
EmployeeMap
中查找start_date
小于sale_date
且end date
大于它的行(除了empl_num
上的相等条件外) .幸运的是,前面提到的data.table包提供了应用所述逻辑的能力 .
请注意,所有三个日期列都应该是日期类型,而不是字符串,以便进行比较 . 另请注意,上面输出中的
NA
值是问题中提供的EmployeeMap
快照的结果,该快照仅映射empl_num
1-4 .我还建议阅读this question的答案,了解如何加入日期范围的更多背景信息 .
在SQL术语中,这是一个3向连接 . 它可以在单个SQL select中完成,如下所示:
最后使用Note中的数据(基于所讨论的数据),我们得到以下结果 . 问题中显示的EmployeeMap数据中只存在前4个员工编号,左连接确保我们获得团队的NA值和其他人的技能级别,而不是由于不匹配而丢弃的SalesData行 .
注意
以可重复的形式输入数据: