在匹配一个变量后,只将一个变量从一个 R data.table 复制到另一个
Copy only one variable from one R data.table to another after matching on a variable
我可以通过类似
的方式将数据框中一列的匹配副本复制到另一列
DF2$y <- DF1[match(DF2$id2, DF1$id1), "z"] # DF1 and DF2 are data frames
其中 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
但我担心 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
(其中前两行可以写在一行上)但这似乎有点太复杂了。会有更简单快速的解决方案吗?
谢谢。
示例:
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?
我有两个可能的想法:
- 使用
merge
和 select 列并在那里进行重命名
DT3 <- merge(DT2, DT1[, .(id1, y = z)], by.x = "id2", by.y = "id1", all.x = TRUE)
- 使用
data.table
的 on
语法。我直接根据这里的答案建立了这个解决方案,它展示了如何进行完整的外部连接:
unique_keys <- unique(c(DT1[, id1], DT2[, id2]))
DT3 <- DT2[DT1[.(unique_keys), .(id1, y = z)]]
如果我理解正确,OP 想要将列 z
从 DT1
追加到 DT2
作为 ID 列匹配的列 y
。
使用 data.table,这可以使用 更新连接:
来解决
library(data.table)
DT2[DT1, on = .(id2 = id1), y := i.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
通过引用 更新 ,即没有复制整个数据对象。这对于 OP 的数百万行的大型生产数据集可能很方便。
警告
这是有效的,因为 id1
和 id2
是 唯一的 ,示例用例就是这种情况。因此,请确保在对重复值执行 更新联接 时得到所需内容。
让我们看看如果 id1
列中有重复值会发生什么,例如
万一 DT1
有 id1 == 4
重复
(DT1 <- data.table(id1 = c(2:4, 4), x = LETTERS[1:4], z = 11:14))
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][]
returns
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
以防出现多个匹配项。
我可以通过类似
的方式将数据框中一列的匹配副本复制到另一列DF2$y <- DF1[match(DF2$id2, DF1$id1), "z"] # DF1 and DF2 are data frames
其中 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
但我担心 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
(其中前两行可以写在一行上)但这似乎有点太复杂了。会有更简单快速的解决方案吗?
谢谢。
示例:
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?
我有两个可能的想法:
- 使用
merge
和 select 列并在那里进行重命名
DT3 <- merge(DT2, DT1[, .(id1, y = z)], by.x = "id2", by.y = "id1", all.x = TRUE)
- 使用
data.table
的on
语法。我直接根据这里的答案建立了这个解决方案,它展示了如何进行完整的外部连接:
unique_keys <- unique(c(DT1[, id1], DT2[, id2]))
DT3 <- DT2[DT1[.(unique_keys), .(id1, y = z)]]
如果我理解正确,OP 想要将列 z
从 DT1
追加到 DT2
作为 ID 列匹配的列 y
。
使用 data.table,这可以使用 更新连接:
来解决library(data.table)
DT2[DT1, on = .(id2 = id1), y := i.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
通过引用 更新 ,即没有复制整个数据对象。这对于 OP 的数百万行的大型生产数据集可能很方便。
警告
这是有效的,因为 id1
和 id2
是 唯一的 ,示例用例就是这种情况。因此,请确保在对重复值执行 更新联接 时得到所需内容。
让我们看看如果 id1
列中有重复值会发生什么,例如
万一 DT1
有 id1 == 4
重复
(DT1 <- data.table(id1 = c(2:4, 4), x = LETTERS[1:4], z = 11:14))
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][]
returns
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
以防出现多个匹配项。