我可以通过类似的方法将数据框中的一列的匹配副本复制到另一个数据框中
DF2$y <- DF1[match(DF2$id2, DF1$id1), "z"] # DF1 and DF2 are data frames
Run Code Online (Sandbox Code Playgroud)
其中DF2$id2与 匹配DF1$id1。我想知道我可以用数据表来进行这种操作。我的数据表有数百万行和数百列。我已经完成了setkey(DT1, id1)并且setkey(DT2, id2).
这有效:
DT2[, y := DT1[match(DT2$id2, DT1$id1), "z"]] # DT1 and DT2 are data tables
Run Code Online (Sandbox Code Playgroud)
但我担心这match部分可能会花费比必要的时间更长的时间。(或者这是不可避免的?)
据我所知,我还可以使用列选择、merge和重命名:
tmp <- DT1[, c("id1", "z")] # column selection
DT3 <- merge(DT2, tmp, by.x = "id2", by.y = "id1", all.x = TRUE, suffixes = c("", ".y")) # merge
setnames(DT3, "z.y", "y") # rename
Run Code Online (Sandbox Code Playgroud)
(前两行可以写在一行上)但这似乎有点太复杂了。有没有更简单、快速的解决方案?
谢谢。
例子:
library(data.table)
DF1 <- data.frame(id1=2:4, x=LETTERS[1:3], z=11:13)
DF2 <- data.frame(id2=1:4, x=LETTERS[5:8], z=21:24)
DF1
# id1 x z
# 1 2 A 11
# 2 3 B 12
# 3 4 C 13
DF2
# id2 x z
# 1 1 E 21
# 2 2 F 22
# 3 3 G 23
# 4 4 H 24
DT1 <- data.table(DF1)
DT2 <- data.table(DF2)
setkey(DT1, id1)
setkey(DT2, id2)
DF2$y <- DF1[match(DF2$id2, DF1$id1), "z"]
DF2 # correct
# id2 x z y
# 1 1 E 21 NA
# 2 2 F 22 11
# 3 3 G 23 12
# 4 4 H 24 13
DT2[, y := DT1[match(DT2$id2, DT1$id1), "z"]]
DT2
# id2 x z y
# 1: 1 E 21 NA
# 2: 2 F 22 11
# 3: 3 G 23 12
# 4: 4 H 24 13
DT2[, y := NULL]
tmp <- DT1[, c("id1", "z")]
DT3 <- merge(DT2, tmp, by.x = "id2", by.y = "id1", all.x = TRUE, suffixes = c("", ".y"))
setnames(DT3, "z.y", "y")
DT3
# id2 x z y
# 1: 1 E 21 NA
# 2: 2 F 22 11
# 3: 3 G 23 12
# 4: 4 H 24 13
## Simpler alternatives?
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,OP 想要将列附加z到DT1id列匹配的DT2列。y
对于data.table ,可以使用update join来解决这个问题:
library(data.table)
DT2[DT1, on = .(id2 = id1), y := i.z]
DT2
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)id2 x z y 1: 1 E 21 NA 2: 2 F 22 11 3: 3 G 23 12 4: 4 H 24 13
请注意,是通过引用DT2更新的,即不复制整个数据对象。这对于 OP 的数百万行的大型生产数据集可能很方便。
这是有效的,因为id1和id2是唯一的,这就是示例用例的情况。因此,请确保在更新重复值的联接时获得所需的结果。
让我们看看如果列中有重复值会发生什么id1,例如
如果DT1有id1 == 4重复
(DT1 <- data.table(id1 = c(2:4, 4), x = LETTERS[1:4], z = 11:14))
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)id1 x z 1: 2 A 11 2: 3 B 12 3: 4 C 13 4: 4 D 14
然后
DT2[DT1, on = .(id2 = id1), y := i.z][]
Run Code Online (Sandbox Code Playgroud)
回报
Run Code Online (Sandbox Code Playgroud)id2 x z y 1: 1 E 21 NA 2: 2 F 22 11 3: 3 G 23 12 4: 4 H 24 14
所以,更新加入
DT2(这可能是您可能希望避免复制大型数据集的行),z如果有多个匹配项,则选择最后一次出现的。