R中的“不加入”

kulphzqa  于 12个月前  发布在  其他
关注(0)|答案(6)|浏览(87)

我正在寻找一个快速的方法来做'不加入'(即。保留未合并行,或者与内部连接相反)。我一直在做的方法是使用data.table为X和Y,然后设置键。举例来说:

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的答案更清晰。最后一个障碍是预置数据。表键,如果不用这样做就好了。
编辑:澄清一下,可接受的解决方案是:

merge(anti_join(X, Y, by = 'category'),anti_join(Y, X, by = 'category'), by = 'category', all = TRUE)
qxsslcnc

qxsslcnc1#

require(dplyr)
bind_rows(anti_join(X, Y), anti_join(Y, X))

编辑:既然有人要求解释,下面是正在发生的事情:
第一个anti_join()函数返回X中的行,这些行在Y中没有匹配的行,匹配由联接的联接依据决定。第二种则相反。rbind_list()只是将其输入的结果与来自每个输入的所有观测值一起放入单个tbl中,用NA替换缺失的变量数据。

xwmevbvl

xwmevbvl2#

setkey(X,category)
setkey(Y,category)

rbind(X[!Y], Y[!X], fill = TRUE)
j8yoct9x

j8yoct9x3#

你可以像这样使它更简洁:

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)]
xytpbqjk

xytpbqjk4#

类似于@stanekam的答案,你也可以使用%in%。这就像Rohit使用%in%,但使用了dqr:

require(dplyr)
bind_rows(X |> filter(!category %in% Y$category),
          Y |> filter(!category %in% X$category))

如果在一个数据框中有两列,也可以使用单个筛选语句。为此,我们首先重命名列,以便它们在合并数据框后保留在单独的变量中:

bind_rows(X |> rename(category_X=category), 
          Y |> rename(category_Y=category)) |> 
filter(!category_X %in% category_Y | !category_Y %in% category_X)
wfsdck30

wfsdck305#

试试这个。首先,合并时将“all”设置为“TRUE”。然后取出所有完整的案例:

XY_All <- merge(X,Y,by='category',all=TRUE)
notXY  <- XY_All[!complete.cases(XY_All),]
llew8vvj

llew8vvj6#

require(dplyr)
notXY = merge(X[!X$category %in% Y$category,], Y[!Y$category %in% X$category,],by = 
"category",all = TRUE)

查看Anti-Join的一种方法是,您需要将来自X(不在Y中)的观测和来自Y(不在X中)的观测连接在一起。这可以在如上所示的一个步骤中实现。

相关问题