r中的条件连接

时间:2015-07-18 11:08:13

标签: r join dplyr

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

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的{​​{1}}中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])) 答案的问题,但答案不必使用该包。

2 个答案:

答案 0 :(得分:5)

如果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]

答案 1 :(得分:4)

你想要的是:

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

请参阅?data.table&gt; roll

  

适用于最后一个连接列,通常是日期,但可以是任何有序变量,不规则且包括间隙。如果roll=TRUEi的行与除最后一个x加入列之外的所有行匹配,并且其在最后i加入列中的值落在一个间隙中(包括x中对该组的最后一次观察,然后x中的主导值向前滚动。使用修改的二进制搜索,此操作特别快。该操作也称为最后观察结果(LOCF)。通常,x键中不应有重复项,最后一个键列是日期(或时间或日期时间),x键的所有列都连接到。一个常见的习惯用法是在一组标识符(dts)中选择同期的常规时间序列(ids):DT[CJ(ids,dts),roll=TRUE]其中DT有一个2列的密钥({ {1}})和id,date代表交叉联接。当CJ为正数时,这会限制值向前推进的程度。 roll相当于roll=TRUE。当roll=+Inf为负数时,值会向后滚动;即,下一次观察向后移动(NOCB)。使用roll进行无限制回滚。当滚动为-Inf时,最近的值将连接到。

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