问题 r中的条件连接


我想有条件地将两个数据表连接在一起:

library(data.table)
set.seed(1)

key.table <- 
  data.table(
    out = (0:10)/10,
    keyz = sort(runif(11))
  )

large.tbl <- 
  data.table(
    ab = rnorm(1e6),
    cd = runif(1e6)
  )

根据以下规则:匹配最小值 out 在 key.table 谁的 keyz 值大于 cd。我有以下内容:

library(dplyr)
large.tbl %>%
  rowwise %>%
  mutate(out = min(key.table$out[key.table$keyz > cd]))

它提供了正确的输出。我遇到的问题是 rowwise 操作似乎很昂贵 large.tbl 我实际上正在使用,崩溃它,除非它在特定的计算机上。是否有更少的内存昂贵的操作?以下似乎稍快,但不足以解决我的问题。

large.tbl %>%
    group_by(cd) %>%
    mutate(out = min(key.table$out[key.table$keyz > cd]))

这闻起来像一个问题 data.table 回答,但答案不必使用该包。


11215
2017-07-18 11:08


起源

我赞成你的问题,因为其他人都做了^ ^。 - Tim Biegeleisen
我认为如果您认为使用特定包装的潜在解决方案,您应首先尝试解决方案...... - Arun


答案:


你想要的是:

setkey(large.tbl, cd)
setkey(key.table, keyz)
key.table[large.tbl, roll = -Inf]

看到 ?data.table>roll

适用于最后一个连接列,通常是日期,但可以是任何有序变量,不规则且包括间隙。如果 roll=TRUE 和 i除了最后一个,所有的行都匹配 x 连接列,其值在最后 i 连接列落在一个空隙中(包括在最后一次观察之后) x 对于那个组),然后是当前的价值 x 向前滚动。使用修改的二进制搜索,此操作特别快。该操作也称为最后观察结果(LOCF)。通常,应该没有重复 x的关键,最后一个关键列是日期(或时间,或日期时间)和所有列 x关键是加入。一个常见的习语是选择一个同期的常规时间序列(dts)跨越一组标识符(ids): DT[CJ(ids,dts),roll=TRUE] 哪里 DT 有一个2列的键(id,date)和 CJ 代表交叉连接。什么时候 roll 是一个正数,这限制了值的结果。 roll=TRUE 相当于 roll=+Inf。什么时候 roll 是一个负数,值向后滚动;即,下一次观察向后移动(NOCB)。使用 -Inf 无限回滚。滚动的时候 "nearest",最近的值连接到。

(公平地说,我认为这可以用于解释,它非常密集)


4
2017-07-18 15:36



公平地说,我正在详细研究 护身符...我认为data.table用户非常熟悉。 - Arun
我知道,认为这是一个轻柔的推动;-) - MichaelChirico
我怀疑这是正确的答案。但在阅读文档后,我仍然不完全理解这种方法。 - Hugh
现在明白了。我觉得这很有帮助 gormanalysis.com/r-data-table-rolling-joins - Hugh
@Hugh非常酷。我想知道是否有办法将其添加到文档中...... - MichaelChirico


如果 key.table$out 也可以按照您的玩具示例进行排序,以下工作

ind <- findInterval(large.tbl$cd, key.table$keyz) + 1
large.tbl$out <- key.table$out[ind]
head(large.tbl)
#             ab         cd out
#1: -0.928567035 0.99473795  NA
#2: -0.294720447 0.41107393 0.5
#3: -0.005767173 0.91086585 1.0
#4:  2.404653389 0.66491244 0.8
#5:  0.763593461 0.09590456 0.1
#6: -0.799009249 0.50963409 0.5

如果 key.table$out 没有排序,

ind <- findInterval(large.tbl$cd, key.table$keyz) + 1
vec <- rev(cummin(rev(key.table$out)))
large.tbl$out <- vec[ind]

5
2017-07-18 14:12