当使用X [Y]连接data.tables X和Y时,X必须有一个键,Y的键用来进行连接.如果X是一个非常大的表并且通常键入未在连接中使用的列,则需要为连接更改X的键,然后在连接后恢复为原始键.有没有一种有效的方法来进行连接,而不会丢失X上的原始主键?
我有一个大的时间序列环境数据集DT(1M行,36列),作为data.table,在站点和日期列上有键.我需要对DT中的现有列进行计算和/或使用小型查找或重新编码表基于现有列插入新列.
这是一个最小的例子:
require(data.table) # using v1.9.5
# main data table DT, keyed on site and date, with data column x
DT <- data.table(site = rep(LETTERS[1:2], each=3),
date = rep(1:3, times=2),
x = rep(1:3*10, times=2),
key = "site,date")
DT
# site date x
# 1: A 1 10
# 2: A 2 20
# 3: A 3 30
# 4: B 1 10
# 5: B 2 20
# 6: B 3 30
# lookup table for x to y lookup, keyed on x
x2y <- data.table(x = c(10,20), y = c(100,200), key = "x")
x2y
# x y
# 1: 10 100
# 2: 20 200
Run Code Online (Sandbox Code Playgroud)
要将查找表x2y与主表DT连接,我将DT键设置为"x":
setkey(DT,x)
Run Code Online (Sandbox Code Playgroud)
然后连接按预期工作.
DT[x2y]
# site date x y
# 1: A 1 10 100
# 2: B 1 10 100
# 3: A 2 20 200
# 4: B 2 20 200
Run Code Online (Sandbox Code Playgroud)
我可以在计算中使用查找表中的"y"或在DT中创建一个新列.
DT[x2y, y:=y]
# site date x y
# 1: A 1 10 100
# 2: B 1 10 100
# 3: A 2 20 200
# 4: B 2 20 200
# 5: A 3 30 NA
# 6: B 3 30 NA
Run Code Online (Sandbox Code Playgroud)
但现在我的时间序列数据集DT键入"x",我需要将密钥设置回"site,date"以供进一步使用.
setkey(DT,site,date)
Run Code Online (Sandbox Code Playgroud)
当DT非常大(1M行)时,这种方法(键X,连接,然后重新键X)是最快的方法,或者是否有同样有效的方式来执行此类查找连接,而不会丢失原始方法关键在大DT桌上?
更新:由于修复了错误,因此不再需要.请参阅接受的答案.
我会加入x:
DT[,y:=x2y[J(DT$x)]$y]
Run Code Online (Sandbox Code Playgroud)
关键DT是保留在这里.
实施辅助密钥(自 v1.9.6 起)以及最近正确保留/丢弃密钥的错误修复(在 v1.9.7 中)后,您现在可以使用以下命令执行此操作on=:
# join
DT[x2y, on="x"] # key is removed as row order gets changed.
# update using joins
DT[x2y, y:=y, on="x"] # key is retained, as row order isn't changed.
Run Code Online (Sandbox Code Playgroud)