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中的“不加入”的主要内容,如果未能解决你的问题,请参考以下文章

java 为啥文件不加入Source中编译就出现source not found

栈在表达式求值中的应用

删除多表而不加入

AVL树插入操作InsertAVL的实现

r R中的统计测试包括dplyr中的分组

R:从R中的大型数据集中根据列中的值删除行[重复]