tos*_*pig 15 join r data.table
我想了解rolling joins在data.table.最后给出了重现这一点的数据.
给出机场交易的数据表,在给定时间:
> dt
   t_id airport thisTime
1:    1       a      5.1
2:    3       a      5.1
3:    2       a      6.2  
(注t_ids1和3有相同的机场和时间)
以及从机场起飞的航班查询表:
> dt_lookup
   f_id airport thisTime
1:    1       a        6
2:    2       a        6
3:    1       b        7
4:    1       c        8
5:    2       d        7
6:    1       d        9
7:    2       e        8
> tables()
     NAME      NROW NCOL MB COLS                  KEY             
[1,] dt           3    3  1 t_id,airport,thisTime airport,thisTime
[2,] dt_lookup    7    3  1 f_id,airport,thisTime airport,thisTime
我想将所有交易与所有下一个可能从该机场起飞的航班相匹配,以便:
   t_id airport thisTime f_id
      1       a        6    1
      1       a        6    2
      3       a        6    1
      3       a        6    2
所以我认为这会奏效:
> dt[dt_lookup, nomatch=0,roll=Inf]
   t_id airport thisTime f_id
1:    3       a        6    1
2:    3       a        6    2
但它还没有退回交易t_id == 1.
从文档中可以看出:
通常,x的键中不应该有重复,...
但是,我确实在我的'x key'(即airport&thisTime)中有重复项,并且无法完全看到/理解t_id = 1将从输出中删除的内容.
任何人都可以解释为什么t_id = 1不归还,以及如何在重复时让联接工作?
数据
library(data.table)
dt <- data.table(t_id = seq(1:3),
                 airport = c("a","a","a"),
                 thisTime = c(5.1,6.2, 5.1), key=c( "airport","thisTime"))
dt_lookup <- data.table(f_id = c(rep(1,4),rep(2,3)),
                        airport = c("a","b","c","d",
                                 "a","d","e"),
                        thisTime = c(6,7,8,9,
                                 6,7,8), key=c("airport","thisTime"))
Jaa*_*aap 23
t_id = 1未在输出中显示的原因是因为滚动连接采用最后发生键组合的行.从文档(强调我的):
适用于最后一个连接列,通常是日期,但可以是任何有序变量,不规则且包括间隙.如果roll = TRUE并且i的行与除最后一个x join列之外的所有行匹配,并且它在最后一个i join列中的值落在一个间隙中(包括在该组中x的最后一次观察之后),那么x中的主导值是向前滚动.使用修改的二进制搜索,此操作特别快.该操作也称为最后观察结果(LOCF).
让我们考虑一些更大的数据集:
> DT
   t_id airport thisTime
1:    1       a      5.1
2:    4       a      5.1
3:    3       a      5.1
4:    2       d      6.2
5:    5       d      6.2
> DT_LU
   f_id airport thisTime
1:    1       a        6
2:    2       a        6
3:    2       a        8
4:    1       b        7
5:    1       c        8
6:    2       d        7
7:    1       d        9
当您执行滚动连接时,就像在您的问题中一样:
DT[DT_LU, nomatch=0, roll=Inf]
你得到:
   t_id airport thisTime f_id
1:    3       a        6    1
2:    3       a        6    2
3:    3       a        8    2
4:    5       d        7    2
5:    5       d        9    1
如您所见,从组合键a, 5.1和d, 6.2最后一行用于连接数据表.由于您将其Inf用作滚动值,因此所有未来值都将合并到生成的数据表中.当你使用:
DT[DT_LU, nomatch=0, roll=1]
你看到只包括未来的第一个值:
   t_id airport thisTime f_id
1:    3       a        6    1
2:    3       a        6    2
3:    5       d        7    2
如果你想f_id的为的所有组合airport与thisTime其中DT$thisTime低于DT_LU$thisTime,您可以通过创建一个新的变量(或替换现有的做到这一点thisTime)的通过手段ceiling的功能.我创建一个新变量thisTime2然后执行普通连接的示例DT_LU:
DT[, thisTime2 := ceiling(thisTime)]
setkey(DT, airport, thisTime2)[DT_LU, nomatch=0]
这使:
   t_id airport thisTime thisTime2 f_id
1:    1       a      5.1         6    1
2:    4       a      5.1         6    1
3:    3       a      5.1         6    1
4:    1       a      5.1         6    2
5:    4       a      5.1         6    2
6:    3       a      5.1         6    2
7:    2       d      6.2         7    2
8:    5       d      6.2         7    2
适用于您提供的数据:
> dt[, thisTime2 := ceiling(thisTime)]
> setkey(dt, airport, thisTime2)[dt_lookup, nomatch=0]
   t_id airport thisTime thisTime2 f_id
1:    1       a      5.1         6    1
2:    3       a      5.1         6    1
3:    1       a      5.1         6    2
4:    3       a      5.1         6    2
如果要包含未来的值而不是仅包含第一个值,则需要一种稍微不同的方法,您将需要该i.col功能(尚未记录):
1:首先将键设置为仅airport列:
setkey(DT, airport)
setkey(DT_LU, airport)
2:使用i.col功能(尚未记录)j获取您想要的内容,如下所示:
DT1 <- DT_LU[DT, .(tid = i.t_id,
                   tTime = i.thisTime,
                   fTime = thisTime[i.thisTime < thisTime],
                   fid = f_id[i.thisTime < thisTime]),
             by=.EACHI]
这给你:
> DT1
    airport tid tTime fTime fid
 1:       a   1   5.1     6   1
 2:       a   1   5.1     6   2
 3:       a   1   5.1     8   2
 4:       a   4   5.1     6   1
 5:       a   4   5.1     6   2
 6:       a   4   5.1     8   2
 7:       a   3   5.1     6   1
 8:       a   3   5.1     6   2
 9:       a   3   5.1     8   2
10:       d   2   6.2     7   2
11:       d   2   6.2     9   1
12:       d   5   6.2     7   2
13:       d   5   6.2     9   1
一些解释:如果您要连接两个使用相同列名的数据表,您可以通过在列名i前面引用数据表的列i..现在,您可以比较thisTime来自DT与thisTime从DT_LU.有了by = .EACHI你保证,对于与条件成立的所有组合都包括在结果DataTable.
或者,您可以实现相同的目标:
DT2 <- DT_LU[DT, .(airport=i.airport,
                   tid=i.t_id,
                   tTime=i.thisTime,
                   fTime=thisTime[i.thisTime < thisTime],
                   fid=f_id[i.thisTime < thisTime]),
             allow.cartesian=TRUE]
这给出了相同的结果:
> identical(DT1, DT2)
[1] TRUE
当您只想在某个边界内包含未来值时,您可以使用:
DT1 <- DT_LU[DT, 
             {
               idx = i.thisTime < thisTime & thisTime - i.thisTime < 2
               .(tid  = i.t_id,
                 tTime = i.thisTime,
                 fTime = thisTime[idx],
                 fid = f_id[idx])
               },
             by=.EACHI]
这使:
> DT1
   airport tid tTime fTime fid
1:       a   1   5.1     6   1
2:       a   1   5.1     6   2
3:       a   4   5.1     6   1
4:       a   4   5.1     6   2
5:       a   3   5.1     6   1
6:       a   3   5.1     6   2
7:       d   2   6.2     7   2
8:       d   5   6.2     7   2
将其与上一个结果进行比较时,您会看到现在已删除第3,6,9,10和12行.
数据:
DT <- data.table(t_id = c(1,4,2,3,5),
                 airport = c("a","a","d","a","d"),
                 thisTime = c(5.1, 5.1, 6.2, 5.1, 6.2),
                 key=c("airport","thisTime"))
DT_LU <- data.table(f_id = c(rep(1,4),rep(2,3)),
                    airport = c("a","b","c","d","a","d","e"),
                    thisTime = c(6,7,8,9,6,7,8),
                    key=c("airport","thisTime"))