从 SO 上的其他地方窃取一个虚拟示例(在确切日期加入 data.table,或者如果不是在最近的小于日期的情况下加入)),我希望根据严格更早的第一个日期(Dt1 中的日期)加入两个表比第二个日期(Dt2 中的日期)。
还关闭了 DataCombine 解决方案“幻灯片”功能中的“警告”消息,因为它可能不公平地减慢了 mtotos 解决方案的速度。
library(data.table)
Dt1 <- read.table(text="
date x
1/26/2010, 10
1/25/2010, 9
1/24/2010, 9
1/22/2010, 7
1/19/2010, 11", header=TRUE, stringsAsFactors=FALSE)
Dt2 <- read.table(text="
date
1/26/2010
1/23/2010
1/20/2010", header=TRUE, stringsAsFactors=FALSE)
Run Code Online (Sandbox Code Playgroud)
加入所需的结果
date x
1/26/2010 - 9 # based on closest observation strictly less than date
1/23/2010 - 7
1/20/2010 - 11
Run Code Online (Sandbox Code Playgroud)
(我保留 data.frame 格式用于输入 mtoto 的解决方案,而 data.table 则用于 jangorecki 的解决方案)。
solution.mtoto = function(Df1, Df2)
{
#Full outer join of two df's
merged <- merge(Df1, Df2, by = "date", all = T, sort=T)
# Shifting values backwards by one using 'slide' from DataCombine
merged <- slide(merged, Var = "x", slideBy = -1, reminder = F)
# Inner join retaining the relevant cols
return(merge(Df2,merged)[,-2])
}
solution.jangorecki = function(Dt1, Dt2)
{
offset.roll.join = function(Dt1, Dt2){
Dt2[, jndate := date - 1L] # produce join column with offset
on.exit(Dt2[, jndate := NULL]) # cleanup join col on exit
Dt1[Dt2, .(date = i.date, x), on = c("date" = "jndate"), roll = Inf] # do rolling join
}
return(offset.roll.join(Dt1, Dt2))
}
res.mtoto = sapply(1:10, FUN = function(x){system.time({solution.mtoto(Df1, Df2)})})
res.jangorecki = sapply(1:10, FUN = function(x){system.time({solution.jangorecki(Dt1, Dt2)})})
> res.mtoto[c("user.self", "sys.self"),]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
user.self 0.004 0.004 0.004 0.004 0.003 0.003 0.003 0.003 0.003 0.003
sys.self 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
> res.jangorecki[c("user.self", "sys.self"),]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
user.self 0.005 0.005 0.004 0.004 0.005 0.004 0.004 0.004 0.003 0.004
sys.self 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
Run Code Online (Sandbox Code Playgroud)
编辑,在 mtoto 的解决方案中意外引用了 Dt1 而不是 Df1。现在已修复。
相似的速度(在更大的数据集上可能更明显?)。我的另一个问题是我希望在第二个表中返回日期。
例如,期望的结果是:
date - x - date2
1/26/2010 - 9 - 1/25/2010
1/23/2010 - 7 - 1/22/2010
1/20/2010 - 11 - 1/19/2010
Run Code Online (Sandbox Code Playgroud)
带偏移的滚动连接-1L。
2016-04-02 更新:通过当前开发 v1.9.7 中的此提交,无需创建临时列即可完成此操作。来自新闻:
x 的列可以随时
j使用前缀来引用。x.当需要将 x 的列同时作为连接列时,这尤其有用。这是一个解决#1615的补丁。
Dt2[, jndate := date - 1L]
Dt1[Dt2,
.(date = i.date, orgdate = x.date, x),
on = c("date" = "jndate"),
roll = Inf]
# date orgdate x
#1: 2010-01-26 2010-01-25 9
#2: 2010-01-23 2010-01-22 7
#3: 2010-01-20 2010-01-19 11
Run Code Online (Sandbox Code Playgroud)
原始答案,如果您使用的是 1.9.6 或更早版本,则很有用。
library(data.table)
# data
Dt1 = fread("date x
1/26/2010, 10
1/25/2010, 9
1/24/2010, 9
1/22/2010, 7
1/19/2010, 11")[, date := as.IDate(date, format=("%m/%d/%Y"))][]
Dt2 = fread("date
1/26/2010
1/23/2010
1/20/2010")[, date := as.IDate(date, format=("%m/%d/%Y"))][]
# solution
offset.roll.join = function(Dt1, Dt2){
Dt2[, jndate := date - 1L] # produce join column with offset
Dt1[, orgdate := date] # should not be needed after data.table#1615
on.exit({Dt2[, jndate := NULL]; Dt1[, orgdate := NULL]}) # cleanup on exit
Dt1[Dt2, .(date = i.date, orgdate, x), on = c("date" = "jndate"), roll = Inf] # do rolling join
}
offset.roll.join(Dt1, Dt2)
# date orgdate x
#1: 2010-01-26 2010-01-25 9
#2: 2010-01-23 2010-01-22 7
#3: 2010-01-20 2010-01-19 11
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1377 次 |
| 最近记录: |