R setdiff()由正则表达式

时间:2016-02-06 01:13:34

标签: regex r

是否可以使用正则表达式自定义setdiff以查看一个向量而不是另一个向量中的内容?例如:

x <- c("1\t119\t120\t1\t119\t120\tABC\tDEF\t0", "2\t558\t559\t2\t558\t559\tGHI\tJKL\t0", "3\t139\t141\t3\t139\t141\tMNO\tPQR\t0", "3\t139\t143\t3\t139\t143\tSTU\tVWX\t0")

[1] "1\t119\t120\t1\t119\t120\tABC\tDEF\t0"
[2] "2\t558\t559\t2\t558\t559\tGHI\tJKL\t0"       
[3] "3\t139\t141\t3\t139\t141\tMNO\tPQR\t0"   
[4] "3\t139\t143\t3\t139\t143\tSTU\tVWX\t0"   

y <- c("1\t119\t120\t1\t109\t120\tABC\tDEF\t0", "2\t558\t559\t2\t548\t559\tGHI\tJKL\t0", "3\t139\t141\t3\t129\t141\tMNO\tPQR\t0", "3\t139\t143\t3\t129\t143\tSTU\tVWX\t0", "4\t157\t158\t4\t147\t158\tXWX\tYTY\t0", "5\t158\t159\t5\t148\t159\tPHP\tWZW\t0")

[1] "1\t119\t120\t1\t109\t120\tABC\tDEF\t0"
[2] "2\t558\t559\t2\t548\t559\tGHI\tJKL\t0"       
[3] "3\t139\t141\t3\t129\t141\tMNO\tPQR\t0"   
[4] "3\t139\t143\t3\t129\t143\tSTU\tVWX\t0"   
[5] "4\t157\t158\t4\t147\t158\tXWX\tYTY\t0"  
[6] "5\t158\t159\t5\t148\t159\tPHP\tWZW\t0" 

我希望能够证明:

[5] "4\t157\t158\t4\t147\t158\tXWX\tYTY\t0"  
[6] "5\t158\t159\t5\t148\t159\tPHP\tWZW\t0" 

是新的,因为4\t157\t1584\t157\t158y是唯一的。这不起作用:

> setdiff(y,x)
[1] "1\t119\t120\t1\t109\t120\tABC\tDEF\t0" "2\t558\t559\t2\t548\t559\tGHI\tJKL\t0"
[3] "3\t139\t141\t3\t129\t141\tMNO\tPQR\t0" "3\t139\t143\t3\t129\t143\tSTU\tVWX\t0"
[5] "4\t157\t158\t4\t147\t158\tXWX\tYTY\t0" "5\t158\t159\t5\t148\t159\tPHP\tWZW\t0"  

因为第5列在xy中明显不同。我想setdiff仅基于前三列。

setdiff的简单示例可在此处找到:How to tell what is in one vector and not another?

2 个答案:

答案 0 :(得分:4)

执行此操作的一种方法是将xy设为data.frame并进行反连接。我会使用data.table,因为我发现它更自然。

library(data.table)
xDT <- as.data.table(do.call("rbind", strsplit(x, split = "\t")))
yDT <- as.data.table(do.call("rbind", strsplit(y, split = "\t")))

现在反加入(&{34; setdiff&#34;用于data.frame s / data.table s):

yDT[!xDT, on = paste0("V", 1:3)]
#    V1  V2  V3 V4  V5  V6  V7  V8 V9
# 1:  4 157 158  4 147 158 XWX YTY  0
# 2:  5 158 159  5 148 159 PHP WZW  0

您还可以获得行索引(感谢@Frank提供的建议改进/简化):

> yDT[!xDT, which = TRUE, on = paste0("V", 1:3)]

或直接从y

中提取
> y[yDT[!xDT, which = TRUE, on = paste0("V", 1:3)]]
# [1] "4\t157\t158\t4\t147\t158\tXWX\tYTY\t0" "5\t158\t159\t5\t148\t159\tPHP\tWZW\t0"

答案 1 :(得分:3)

我们也可以在使用anti_join

阅读后dplyr使用fread
library(data.table)
library(dplyr)
anti_join(fread(paste(y, collapse='\n')), 
        fread(paste(x, collapse='\n')), by = c('V1', 'V2', 'V3'))

#      V1    V2    V3    V4    V5    V6    V7    V8    V9
#    (int) (int) (int) (int) (int) (int) (chr) (chr) (int)
# 1     4   157   158     4   147   158   XWX   YTY     0
# 2     5   158   159     5   148   159   PHP   WZW     0

或者(作为regex的标题请求)我们可以使用正则表达式删除部分字符串,然后执行%in%

y[!sub('(([^\t]+\t){3}).*', '\\1', y) %in% 
     sub('(([^\t]+\t){3}).*', '\\1', x)]
#[1] "4\t157\t158\t4\t147\t158\tXWX\tYTY\t0" "5\t158\t159\t5\t148\t159\tPHP\tWZW\t0"