我正在尝试实现如下所示的“ Final.Data”输出。
我们从参考数据开始,我想添加“ Add.Data”,但要加入“人”并返回参考(日期)之前的最新结果。
我正在r中寻找dplyr,data.table或sql解决方案。
然后,我希望能够复制1000个条目,因此寻求合理的有效解决方案。
library(tibble)
Reference.Data <- tibble(Person = "John",
Date = "2019-07-10")
Add.Data <- tibble(Person = "John",
Order.Date = c("2019-07-09","2019-07-08") ,
Order = 1:2)
Final.Data <- tibble(Person = "John",
Date = "2019-07-10",
Order.Date = "2019-07-09",
Order = 1)
答案 0 :(得分:4)
到最近日期的最近加入应该很快。.
#data preparation:
# convert to data.tables, set dates as 'real' dates
DT1 <- setDT(Reference.Data)[, Date := as.IDate( Date )]
DT2 <- setDT(Add.Data)[, Order.Date := as.IDate( Order.Date )]
#set keys (this also orders the dates, convenient for the join later)
setkey(DT1, Person, Date)
setkey(DT2, Person, Order.Date)
#perform rolling update join on DT1
DT1[ DT2, `:=`( Order.date = i.Order.Date, Order = i.Order), roll = -Inf][]
# Person Date Order.date Order
# 1: John 2019-07-10 2019-07-09 1
答案 1 :(得分:3)
一种使用data.table
非等额联接并直接在Reference.Data
上进行引用更新的方法:
library(data.table)
setDT(Add.Data)
setDT(Reference.Data)
setorder(Add.Data, Person, Order.Date)
Reference.Data[, (names(Add.Data)) :=
Add.Data[.SD, on=.(Person, Order.Date<Date), mult="last",
mget(paste0("x.", names(Add.Data)))]
]
输出:
Person Date Order.Date Order
1: John 2019-07-10 2019-07-09 1
答案 2 :(得分:2)
另一种data.table
解决方案:
setDT(Add.Data)[, Order.Date := as.Date(Order.Date)]
setDT(Reference.Data)[, Date := as.Date(Date)]
Reference.Data[, c("Order.Date", "Order") := Add.Data[.SD,
on = .(Person, Order.Date = Date),
roll = TRUE,
.(x.Order.Date, x.Order)]]
Reference.Data
# Person Date Order.Date Order
# 1: John 2019-07-10 2019-07-09 1
答案 3 :(得分:1)
我们可以先进行inner_join
,然后按'Person'分组,slice
将max
'Order.Date'所在的行
library(tidyverse)
inner_join(Add.Data, Reference.Data) %>%
group_by(Person) %>%
slice(which.max(as.Date(Order.Date)))
# A tibble: 1 x 4
# Groups: Person [1]
# Person Order.Date Order Date
# <chr> <chr> <int> <chr>
#1 John 2019-07-09 1 2019-07-10
或使用data.tabl#
library(data.table)
setDT(Add.Data)[as.data.table(Reference.Data), on = .(Person)][,
.SD[which.max(as.Date(Order.Date))], by = Person]
答案 4 :(得分:0)
将Reference.Data
与Add.Data
上的Person
相连,并在Order.Date
或之前的Date
处加入。按原始的Reference.Data
行将其分组,并从中获取最大的Order.Date
。它的工作方式是,用于Add.Data
每行的Reference.Data
行将是具有最大Order.Date
的行,因此将显示正确的Order
。 / p>
请注意,点是一个SQL运算符,而order
是一个SQL关键字,因此我们必须在名称周围加上点号或在名称order
(无论大小写)之间加上方括号。
library(sqldf)
sqldf("select r.*, max(a.[Order.Date]) as [Order.Date], a.[Order]
from [Reference.Data] as r
left join [Add.Data] as a on r.Person = a.Person and a.[Order.Date] <= r.Date
group by r.rowid")
给予:
Person Date Order.Date Order
1 John 2019-07-10 2019-07-09 1
我还没有检查这有多快(添加索引可以根据需要加快速度),但是只有几千行的效率并没有可读性那么重要。