R 使用重复键在data.table上滚动联接
我试图理解R 使用重复键在data.table上滚动联接,r,join,data.table,R,Join,Data.table,我试图理解data.table中的滚动联接。最后给出了重现这一点的数据 给定机场在给定时间的交易数据表: > dt t_id airport thisTime 1: 1 a 5.1 2: 3 a 5.1 3: 2 a 6.2 (注意t_id1和3具有相同的机场和时间) 以及从机场起飞的航班查询表: > dt_lookup f_id airport thisTime 1: 1
data.table
中的滚动联接。最后给出了重现这一点的数据
给定机场在给定时间的交易数据表:
> dt
t_id airport thisTime
1: 1 a 5.1
2: 3 a 5.1
3: 2 a 6.2
(注意t_id
1和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\u id==1
从中可以看出:
通常,x的键中不应该有重复项
但是,我的“x键”(即机场
&这次
)中确实有重复项,我不能完全理解从输出中删除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"))
库(data.table)
dt输出中没有显示t_id=1
的原因是滚动联接取最后出现组合键的行。从文件(我的重点):
应用于最后一个联接列,通常是日期,但可以是任意日期
有序变量,不规则,包括间隙。如果roll=TRUE,而我是
行与除最后一个x联接列以外的所有列匹配,其值在
最后一个i连接列落在间隙中(包括最后一个之后
在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]
你会得到:
如您所见,从键组合a,5.1
和d,6.2
中,最后一行用于联接的数据表。因为您使用Inf
作为滚动值,所以所有未来值都合并到结果数据表中。使用时:
DT[DT_LU, nomatch=0, roll=1]
您可以看到,只包含将来的第一个值:
如果您希望DT$thisTime
低于DT\LU$thisTime
的所有airport
和thisTime
组合的f\u id
,可以通过上限功能创建新变量(或替换现有的thisTime
)来实现。例如,我创建了一个新变量thisTime2
,然后与DT\u LU
进行正常连接:
DT[, thisTime2 := ceiling(thisTime)]
setkey(DT, airport, thisTime2)[DT_LU, nomatch=0]
其中:
应用于您提供的数据:
当您希望包含所有未来值而不仅仅是第一个值时,您需要一种稍有不同的方法,您需要i.col
功能(尚未记录):
1:首先仅将键设置为机场列:
setkey(DT, airport)
setkey(DT_LU, airport)
2:使用j
中的i.col
功能(尚未文档化)获得所需内容,如下所示:
DT1 <- DT_LU[DT, .(tid = i.t_id,
tTime = i.thisTime,
fTime = thisTime[i.thisTime < thisTime],
fid = f_id[i.thisTime < thisTime]),
by=.EACHI]
一些说明:如果要连接使用相同列名的两个数据表,可以通过在列名前面加上i.
来引用i
中的数据表列。现在可以将DT
中的与DT\LU
中的进行比较。使用by=.EACHI
可以确保条件保持的所有组合都包含在结果数据表中
或者,您可以通过以下方式实现相同的目标:
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]
如果只希望在特定边界内包含未来值,可以使用:
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]
当您将其与上一个结果进行比较时,您会看到现在第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"))
DT很好的解释——“滚动连接在键组合最后出现的那一行”——是我理解的关键。谢谢。你的天花
示例在这种情况下效果很好,但我预计当dt$thisTime2
值与它试图匹配的dt\u lookup$thisTime
值的时间单位超过1
时,它将不起作用,因此我可能不得不想出一个替代方案?我认为这可能是我见过的最好答案之一!感谢您抽出时间介绍一些新技术。@tospig这可能很有趣:我问了一个关于我在解决您的问题时遇到的一些奇怪现象的问题。@tospig基于,我再次更新了我的答案。这些改进将防止您遇到与我遇到的相同的怪事。
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
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
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"))