如何使用{data.table}在R中将数据连接到仅第一个匹配行?

5
我有一个查找表,其中“第一次”在列d中。例如,患者因特定疾病而首次入院的时间。我想通过data.table将其与多个其他条件的主数据框连接起来。
我的问题是,不幸的是,主数据表可能具有相同的连接条件,这会导致加入后每个患者有多个“第一次”。现实世界的数据很混乱!
是否可以仅在第一次匹配记录上进行{data.table}连接?
这类似于this question,但多个匹配是在主数据表上进行的。我认为mult仅适用于要加入的表格中有几个条目的情况。
repex:
library(data.table)

set.seed(1724)

d1 <- data.table(a = c(1, 1, 1),
                 b = c(1, 1, 2),
                 c = sample(1:10, 3))

d2 <- data.table(a = 1, b = 1, d = TRUE)

d2[d1, on = c("a", "b")]

   a b    d c
1: 1 1 TRUE 4
2: 1 1 TRUE 8
3: 1 2   NA 2

期望的输出

   a b    d c
1: 1 1 TRUE 4
2: 1 1   NA 8
3: 1 2   NA 2

1
简单的解决方案是对每一行进行索引,并在此基础上进行连接(第一个表是主表的筛选版本),但我很想知道是否有更优雅的解决方案。 - Paul
请将您的评论发布为答案,这仍然是一个不错的选择。 - zx8754
1
您可以使用 duplicated 命令找到需要设置为 NA 的位置。 - bdecaf
2
看起来你想要一个“更新连接”:d1[d2, on = .(a, b), d := d, mult = "first"] - Henrik
@Henrik - 很好 - d1[d2, on = .(a, b), (names(d2)) := ..d2, mult = "first"] 或者类似的东西,如果有很多变量,可能要做所有变量? - thelatemail
@Henrik - 我认为在这种情况下确实会发生,但我正在尝试(也许不成功)考虑可能存在变量/数据集名称冲突的情况。 - thelatemail
3个回答

4
library(data.table)
set.seed(1724)
d1 = data.table(a = c(1, 1, 1), b = c(1, 1, 2), c = sample(1:10, 3))
d2 = data.table(a = 1, b = 1, d = TRUE)

d1[, i1:=seq_len(.N), by=c("a","b")]
d2[, i2:=seq_len(.N), by=c("a","b")]

d2[d1, on = c("a","b","i2==i1")][, "i2":=NULL][]
#       a     b      d     c
#   <num> <num> <lgcl> <int>
#1:     1     1   TRUE     4
#2:     1     1     NA     8
#3:     1     2     NA     2

1
我第一次看到 on 的语法是这样的 ("i2==i1")。 - s_baldur

3
一种方法是在合并后将数值更改为NA
library(data.table)

d3 <- d2[d1, on = c("a", "b")]
d3[, d:= replace(d, seq_len(.N) != 1, NA), .(a, b)]
d3

#   a b    d c
#1: 1 1 TRUE 4
#2: 1 1   NA 8
#3: 1 2   NA 2

0

简单的解决方案是对每一行进行索引,并在此基础上进行连接(d2 是 d1 的筛选版本):

library(data.table)

set.seed(1724)

d1 <- data.table(a = c(1, 1, 1),
                 b = c(1, 1, 2),
                 c = sample(1:10, 3))

d1[, rid := seq(to = .N)]
d2 <- d1[, .SD[1], by = c("a"), .SDcols = c("b", "rid")][, d := TRUE] # UPDATE

d2[d1, on = c("a", "b", "rid")]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接