检查向量是否包含另一个向量

时间:2013-09-10 13:13:39

标签: r

我想检查一个向量y是否包含另一个向量x

y <- c(0,0,0,NA,NA,0)
x <- c(0,0,0,0)

在这种情况下,它应该给我FALSE,因为y中没有四个NULL的序列。但是,如果我们查看向量y2,结果应为TRUE

y2 <- c(0,0,NA,0,0,0,0)

修改

我尝试使用%in%,但它似乎只适用于矢量元素,而不适用于整个矢量。该解决方案不一定适用于更普遍的问题。如果它适用于这种特殊情况会很好。

7 个答案:

答案 0 :(得分:7)

您可以使用greplpaste的组合。在这里,您需要使用collapse中的paste参数将每个向量折叠为一个字符。

> grepl(paste(x,collapse=";"),paste(y2,collapse=";"))
[1] TRUE
> grepl(paste(x,collapse=";"),paste(y,collapse=";"))
[1] FALSE

> grepl(paste(c(123),collapse=";"),paste(c(12,3),collapse=";"))
[1] FALSE

答案 1 :(得分:5)

使用此:

any(apply(embed(y,length(y)-length(x)+1),2,identical,x))

答案 2 :(得分:4)

只为那些可能会怀疑的人,对答案进行时间测试。

findit1<-function(x,y) any(apply(embed(y,length(y)-length(x)+1),2,identical,x))
findit2<-function(x,y) grepl(paste(x,collapse=";"),paste(y,collapse=";"))

x<-c(0,1,1,0,0,0,1,0,1)
y<-sample(c(0,1),1e5,replace=TRUE)

Rgames> microbenchmark(findit1(x,y),findit2(x,y))
Unit: milliseconds
          expr       min       lq   median       uq      max neval
 findit1(x, y) 403.79291 449.9028 457.8320 466.4996 603.6573   100
 findit2(x, y)  99.09317 100.7774 101.4513 102.1728 119.8970   100

编辑: 使用eddi的rle答案,

Rgames> findit3<-function(x,y) sum(length(x) <= rle(y)$lengths[rle(y)$values %in% 0]) 
Rgames> x<-c(0,0,0,0,0)
Rgames> microbenchmark(findit1(x,y),findit2(x,y),findit3(x,y))
Unit: milliseconds
          expr       min        lq   median        uq       max neval
 findit1(x, y) 340.63570 383.39450 414.6791 456.38786 532.98017   100
 findit2(x, y)  99.72606 101.11308 101.9399 103.20869 117.91149   100
 findit3(x, y)  23.39226  24.39826  31.8478  35.10592  53.15408   100

但是在x中任何序列的一般情况下,我怀疑是否有办法按摩rleseqle来执行此操作。我将不得不去玩一段时间。 :-)

答案 3 :(得分:3)

对于x中仅0的特定情况,只需使用rle

sum(length(x) <= rle(y2)$lengths[rle(y2)$values %in% 0]) > 0
#[1] TRUE
sum(length(x) <= rle(y)$lengths[rle(y)$values %in% 0]) > 0
#[1] FALSE

答案 4 :(得分:1)

OP没有要求这样做,但是这里有一种方法可以找到x的实例出现的位置。  假设“9”永远不会出现在y中,我使用“9”作为我的标记字符。显然,人们可以选择其他角色。

 > bar<-gsub(paste(x,collapse=""),'9',paste(y,collapse=""))
 > rab<-as.numeric(unlist(strsplit(bar,'')))
 > rle(rab==9)
Run Length Encoding
  lengths: int [1:3123] 49 1 49 1 20 1 6 1 78 1 ...
  values : logi [1:3123] FALSE TRUE FALSE TRUE FALSE TRUE ...

答案 5 :(得分:0)

又一个选择:

length(x) == max(nchar(strsplit(paste(y,collapse=''),"NA")[[1]]))
length(x) == max(nchar(strsplit(paste(y2,collapse=''),"NA")[[1]]))

我还认为应该有更聪明的方法,例如以某种方式使用cumsum(并在每次出现NA时将其重置为0,然后获得最大值并将其与x的长度进行比较)。经过一些互联网搜索,我有:

length(x) == max(sapply(split(y, replace(cumsum(is.na(y)), is.na(y), -1))[-1],length))
length(x) == max(sapply(split(y2, replace(cumsum(is.na(y2)), is.na(y2), -1))[-1],length))

或者也许以which(is.na(x))开头,然后以某种方式计算结果中元素之间的最大差异。

答案 6 :(得分:0)

类似于费迪南德(很好地使用embed(),BTW),这将返回所有匹配的向量(如果没有则为空):

which(sapply(1:(length(y)-length(x)+1), function(z) identical(x, y[z:(z+length(x)-1)])))