也许实现这一点的最简单方法是使用两个类似 SQL 的连接(我建议你给出一些像这样 https://en.wikipedia.org/wiki/Join_(SQL)如果您不熟悉连接/关系代数,请阅读)。
许多连接可以通过merge
基础 R 和许多其他流行软件包中的函数(dplyr
, data.table
, sqldf
,仅举几例)在连接操作中提供替代语法或扩展功能。
您的两个连接中的第一个(在SalesData
and EmployeeSales
)可以很容易地完成merge
:
merge(SalesData, EmployeeSales, by = "sale_id")
# sale_id sale_amt int_rate sale_date sale_status empl_name empl_num
# 1 1 7000 10.71 2008-05-01 Fully Paid Dakota 4
# 2 2 10800 13.57 2009-11-01 Fully Paid Dakota 4
# 3 3 7500 10.08 2008-04-01 Fully Paid Kami 9
# ...
然而,第二个连接更为复杂,因为它不是典型的连接等值连接 https://en.wikipedia.org/wiki/Join_(SQL)#Equi-join。相反,连接逻辑需要在以下位置查找行:EmployeeMap
where start_date
小于sale_date
and end date
大于它(除了相等条件empl_num
).
幸运的是,前面提到的data.table https://rstudio-pubs-static.s3.amazonaws.com/52230_5ae0d25125b544caab32f75f0360e775.html包提供了应用所述逻辑的能力。
library(data.table)
# convert all three dataframes to data.table objects
setDT(SalesData) ; setDT(EmployeeSales) ; setDT(EmployeeMap)
EmployeeMap[SalesData[EmployeeSales[, c("sale_id","empl_num")],
on = "sale_id"],
on = .(empl_num, start_date <= sale_date, end_date >= sale_date)]
# empl_num empl_name skill_lvl team start_date end_date sale_id sale_amt int_rate sale_status
# 1: 4 Dakota Beg Red 2008-05-01 2008-05-01 1 7000 10.71 Fully Paid
# 2: 4 Dakota Int Red 2009-11-01 2009-11-01 2 10800 13.57 Fully Paid
# 3: 9 NA NA NA 2008-04-01 2008-04-01 3 7500 10.08 Fully Paid
# ...
请注意,为了进行比较,所有三个日期列都应该是日期类型,而不是字符串。另请注意,NA
上面输出中的值是快照的结果EmployeeMap
问题中提供,仅映射empl_num
1-4.
我还建议阅读以下答案这个问题 https://stackoverflow.com/questions/23934361/merge-2-dataframes-if-value-within-range有关如何在日期范围内加入的更多背景信息。