问题
我正在尝试使用3个ID列合并两个数据帧(或者1列,如果我将3个粘贴在一起),其中一个是日期时间变量,并且可以在两个数据帧之间变化最多1秒。
背景
我从具有交易记录的库中提取了两个数据帧。出于某种原因,结账和签到是单独记录的,没有唯一的交易ID"匹配他们。我想要匹配它们。 "退房" dataframe具有已签出的每个项目的记录,包括截止日期(应返回该项目时)。 "办理登机手续" dataframe包含已签入的每个项目的记录,包括截止日期。不幸的是,由于两个原因,我很难将这些数据帧合并在一起:
due_date的变化似乎是随机发生的,因此无法确定两个due_dates相等或相差1秒的记录。否则,我可以减去(或添加)一秒钟以使它们相等。
数据
以下是我正在使用的数据示例:
library(dplyr)
library(lubridate)
check_in <- tribble(
~ patron_id, ~item_id, ~checked_in, ~due_date,
"A", "Z", "2018-04-16 07:00:00", "2018-04-16 08:00:00",
"A", "Y", "2018-04-17 07:30:01", "2018-04-17 08:30:01",
"B", "X", "2018-04-17 07:00:01", "2018-04-17 08:00:01",
"B", "Z", "2018-04-17 08:00:01", "2018-04-17 09:00:01",
"B", "Z", "2018-04-09 09:00:01", "2018-04-09 10:00:01",
"C", "V", "2018-04-09 09:00:01", "2018-04-09 10:00:01",
"C", "X", "2018-04-09 09:00:01", "2018-04-09 10:00:01")
check_out <- tribble(
~ patron_id, ~item_id, ~checked_out, ~due_date,
"A", "Z", "2018-04-16 06:00:00", "2018-04-16 08:00:01",
"A", "Y", "2018-04-17 06:30:01", "2018-04-17 08:30:00",
"B", "X", "2018-04-17 06:00:01", "2018-04-17 08:00:00",
"B", "Z", "2018-04-17 07:00:01", "2018-04-17 09:00:00",
"B", "Z", "2018-04-09 08:00:01", "2018-04-09 10:00:01",
"C", "V", "2018-04-09 08:00:01", "2018-04-09 10:00:01",
"C", "X", "2018-04-09 08:00:01", "2018-04-09 10:00:00")
check_in$due_date <- ymd_hms(check_in$due_date)
check_in$checked_in <- ymd_hms(check_in$checked_in)
check_out$due_date <- ymd_hms(check_out$due_date)
check_out$checked_out <- ymd_hms(check_out$checked_out)
赞助人ID是签出图书的人的唯一ID。商品ID是商品的唯一ID。签出是签出本书的时间。签入是指书籍签入时。截止日期是书籍到期的时间。
对于此样本数据,我将所有截止日期等于结账日期后的2小时。我还在办理退房日期后的1小时内办理了入住日期。
所需输出
我想采取&#34; checked_in&#34;来自check_in数据帧的变量,并将其与check_out数据帧中的相应事务相匹配。输出将是这样的,但可能有某种生成的事务ID:
desired_output <- tribble(
~patron_id, ~item_id, ~checked_out, ~checked_in, ~due_date,
"A", "Z", "2018-04-16 06:00:00", "2018-04-16 07:00:00", "2018-04-16 08:00:01",
"A", "Y", "2018-04-17 06:30:01", "2018-04-17 07:30:01", "2018-04-17 08:30:00",
"B", "X", "2018-04-17 06:00:01", "2018-04-17 07:00:01", "2018-04-17 08:00:00",
"B", "Z", "2018-04-17 07:00:01", "2018-04-17 08:00:01", "2018-04-17 09:00:00",
"B", "Z", "2018-04-09 08:00:01", "2018-04-09 09:00:01", "2018-04-09 10:00:01",
"C", "V", "2018-04-09 08:00:01", "2018-04-09 09:00:01", "2018-04-09 10:00:01",
"C", "X", "2018-04-09 08:00:01", "2018-04-09 09:00:01", "2018-04-09 10:00:00")
我尝试了什么
ATTEMPT#1:
我已尝试有条件地合并,如this帖子中所述,并进行了以下修改:
check_out <- check_out %>%
mutate(transaction_id = paste(patron_id,"-",item_id,sep=""))
check_in <- check_in %>%
mutate(transaction_id = paste(patron_id,"-",item_id,sep=""))
output <- merge(check_out, check_in, by="transaction_id")[abs(difftime(check_out$due_date, check_in$due_date, units = "secs"))<=1,]
但是这种方法并没有处理相同的交易ID(显然),并创造了比实际更多的记录。
ATTEMPT#2:
恢复原始数据框,我尝试了this post中的解决方案,并进行了以下修改:
output <- cbind(check_out, check_in[
sapply(check_out$due_date,
function(x) which.min(abs(difftime(x, check_in$due_date)))), ])
但是这种方法不考虑&#34;事务ID&#34;,或者更确切地说,我用来创建某种唯一ID的两个关键变量。因此,输出错误。
其他不成功的尝试:
不幸的是,我无法让这些工作。我对这些方法的工作原理并没有信心,也没有产生我想要的东西。很可能是用户错误,因为似乎其他人能够得到类似的东西。
感谢
先谢谢你,如果你能帮助我的话。我倾向于使用Tidyverse提供的工具,但我愿意使用其他工具和方法。我试图确保在搜索其他解决方案时做了尽职调查,但如果您发现我错过了重要帖子,请将此标记为重复,并按照我的方式发送该帖子。
如果我能提供任何其他信息或澄清上述任何细节,请告诉我。
答案 0 :(得分:1)
会这样:
inner_join(check_in, check_out, by = c("patron_id", "item_id")) %>%
filter(abs(difftime(due_date.y, due_date.x, units= "secs"))<=as.difftime(1, format = "%S", units = "secs"))
说明:简单连接+过滤时间差<= 1秒
的行