这个帖子太老了。但我注意到解决方案可以很容易地从原帖中给出的半连接定义中推导出来:
"半连接类似于内连接,只是它只返回
X 的列(不是 Y 的列),并且不重复 X 的行
匹配 Y 的行”
library(data.table)
dt1 <- data.table(ProdId = 1:4,
Product = c("Bread", "Cheese", "Pizza", "Butter"))
dt2 <- data.table(ProdId = c(1, 1, 3, 4, 5),
Company = c("A", "B", "C", "D", "E"))
# semi-join
unique(merge(dt1, dt2, on="ProdId")[, names(dt1), with=F])
ProdId Product
1: 1 Bread
2: 3 Pizza
3: 4 Butter
我只是简单地应用了内部连接的语法,然后仅从第一个表中过滤列,使用unique() 删除第一个表中重复匹配第二个表行的行。
编辑: 仅当我们在第一个表中有唯一行时,上述方法才会匹配dplyr::semi_join() 输出。如果我们需要从第一个表中输出包括重复的所有行,那么我们可以使用下面的fsetdiff() 方法。
另外一行data.table解决办法:
fsetdiff(dt1, dt1[!dt2, on="ProdId"])
ProdId Product
1: 1 Bread
2: 3 Pizza
3: 4 Butter
我刚刚从第一个表中删除了第一个和第二个的反连接。对我来说似乎更简单。如果第一个表有重复行,我们需要:
fsetdiff(dt1, dt1[!dt2, on="ProdId"], all=T)
fsetdiff() 结果与 ,all=T 匹配 dplyr 的输出:
dplyr::semi_join(dt1, dt2, by="ProdId")
ProdId Product
1 1 Bread
2 3 Pizza
3 4 Butter
使用从以前的一篇文章中获取的另一组数据:
x <- data.table(x = c(1,1,1,2), y = c("a", "a", "a", "b"))
y <- data.table(x = c(1, 1), z = 10:11)
使用 dplyr:
dplyr::semi_join(x, y, by="x")
x y
1 1 a
2 1 a
3 1 a
带data.table:
fsetdiff(x, x[!y, on="x"], all=T)
x y
1: 1 a
2: 1 a
3: 1 a
没有,all=T,重复行被删除:
fsetdiff(x, x[!y, on="x"])
x y
1: 1 a