R中的“不加入”
Posted
技术标签:
【中文标题】R中的“不加入”【英文标题】:"Not Join" in R 【发布时间】:2014-08-03 03:14:32 【问题描述】:我正在寻找一种“不加入”的快速方法(即保留未合并的行,或内部联接的逆向)。我一直在做的方式是对 X 和 Y 使用 data.table,然后设置键。例如:
require(data.table)
X <- data.table(category = c('A','B','C','D'), val1 = c(0.2,0.3,0.8,0.7))
Y <- data.table(category = c('B','C','D','E'), val2 = c(2,3,5,7))
XY <- merge(X,Y,by='category')
> XY
category val1 val2
1: B 0.3 2
2: C 0.8 3
3: D 0.7 5
但我需要与此相反,所以我必须这样做:
XY_All <- merge(X,Y,by='category',all=TRUE)
setkey(XY,category)
setkey(XY_All,category)
notXY <- XY_All[!XY] #data.table not join (finally)
> notXY
category val1 val2
1: A 0.2 NA
2: E NA 7
我觉得这很冗长(尤其是来自 data.frame)。我错过了什么吗?
编辑:在更多地考虑不加入后我得到了这个
X <- data.table(category = c('A','B','C','D'), val1 = c(0.2,0.3,0.8,0.7),key = "category")
Y <- data.table(category = c('B','C','D','E'), val2 = c(2,3,5,7), key = "category")
notXY <- merge(X[!Y],Y[!X],all=TRUE)
但 WheresTheAnyKey 下面的答案更清楚。最后一个障碍是预设 data.table 键,最好不必这样做。
编辑:澄清一下,接受的解决方案是:
merge(anti_join(X, Y, by = 'category'),anti_join(Y, X, by = 'category'), by = 'category', all = TRUE)
【问题讨论】:
现在不在R-console前面,但我相信你应该可以使用类似于X[!Y]
的东西
【参考方案1】:
require(dplyr)
rbind_list(anti_join(X, Y), anti_join(Y, X))
编辑: 由于有人要求进行解释,因此发生了以下情况:
第一个anti_join()
函数返回来自X
的行,这些行在Y
中没有匹配的行,匹配由连接所连接的对象确定。第二个则相反。 rbind_list()
只是获取其输入的结果并将它们放入单个 tbl
中,其中包含来自其每个输入的所有观察结果,用 NA
替换缺失的变量数据。
【讨论】:
不能这样工作。要使用 anti_join 获得预期结果,您需要merge(anti_join(X, Y, by = 'category'),anti_join(Y, X, by = 'category'), by = 'category', all = TRUE)
对不起。再迈一步:)
不仅仅是代码,您还应该解释您正在做什么以及它为什么回答问题。
@azurefrog 这是你的解释 :)
此解决方案不需要 1)需要转换为 data.table 2)在合并之前设置密钥。所以向你致敬! (虽然 WheresTheAnyKey 的解决方案如果你只使用 data.table 可能会更方便,因为 anti_join 会将其转换为 data.frame)【参考方案2】:
setkey(X,category)
setkey(Y,category)
rbind(X[!Y], Y[!X], fill = TRUE)
【讨论】:
这将 A 和 E 的值压缩为都标记为“val1”,而 A 为 0.2=val1,E 为 7=val2 好点。刚改了。此解决方案不涉及笛卡尔连接。【参考方案3】:你可以像这样使它更简洁:
X <- data.table(category = c('A','B','C','D'), val1 = c(0.2,0.3,0.8,0.7),key = "category")
Y <- data.table(category = c('B','C','D','E'), val2 = c(2,3,5,7), key = "category")
notXY <- merge(X,Y,all = TRUE)[!merge(X,Y)]
【讨论】:
几乎,我喜欢它!如果没有其他人在没有预设键的情况下提出另一个解决方案,我会接受这个优雅的解决方案。【参考方案4】:试试这个。 首先,将“all”合并为“TRUE”。然后取出所有完整的案例:
XY_All <- merge(X,Y,by='category',all=TRUE)
notXY <- XY_All[!complete.cases(XY_All),]
【讨论】:
这仅在您要合并的表的任何其他列中没有任何NA
值时才有效。
我认为这很好,根据@tanvach 的要求。
不幸的是 MrFlick 是对的,真实的数据集包含很多 NA。但我喜欢这个解决方案在不设置密钥的情况下如何工作,所以请点赞!【参考方案5】:
require(dplyr)
notXY = merge(X[!X$category %in% Y$category,], Y[!Y$category %in% X$category,],by =
"category",all = TRUE)
查看反连接的一种方法是,您需要将来自 X 而非 Y 的观察结果和来自 Y 而非 X 的观察结果连接在一起。如上所示,这可以通过一个步骤来实现。
【讨论】:
以上是关于R中的“不加入”的主要内容,如果未能解决你的问题,请参考以下文章