Is there an R function finding a vector within another vector?

Viewed 73

For example, I have two vectors:

x1 <- c(0,1,2)
x2 <- c(1,2,0,1,2,3,4,5,0,1,0,1,2)

I would like to find the position where x1 is first present x2, which is in this case is 3. I have tried which(), match(), but both seems to find elements, instead of vectors. Is there a R function that can achieve this or a way to construct one?

Thank you!

4 Answers

If you are looking for the first match of 0:

match(x1[1], x2)

But for the whole vector:

> which(apply(t(embed(x2, length(x1))) == rev(x1), 2, all))[1]
[1] 3
> 

Edit:

To give NA on no-match:

cond <- apply(t(embed(x2, length(x1))) == rev(x1), 2, all)
if (any(cond)) which(cond)[1] else NA

Explanation:

This uses embed to split x2 into chunks by the length of x1, and it applies it and detects whether it is equivalent to x1, and gives a boolean vector (or TRUEs and FALSEs). Then finally it uses which to get the index of the occurrences of TRUE, and I use [1] to get the first value.

For the edit, I detect if in the conditioned boolean vector contains any TRUEs, if so, do the same thing as mentioned above, if not, give NA.

One option would be to do rolling comparison.

x1 <- c(0,1,2) 
x2 <- c(1,2,0,1,2,3,4,5,0,1,0,1,2)

which(zoo::rollapply(x2, length(x1), function(x) all(x == x1)))
#[1]  3 11

To get the 1st occurrence -

which(zoo::rollapply(x2, length(x1), function(x) all(x == x1)))[1]
#[1] 3

For all elements for vector x1.

sapply(x1, function(x) match(x,x2))
[1] 3 1 2

Another approach with stringr;

   library(tidyverse)

x1_ <- paste0(x1,collapse="")
x2_ <- paste0(x2,collapse="")
str_locate_all(x2_, x1_)[[1]]

gives,

     start end
[1,]     3   5
[2,]    11  13

which returns empty if there is no match.

Related