Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the nth match of the elements between two vectors in R?

Tags:

r

match returns the position of first matches between its first and second arguments:

match(c("a","c"), c("a", "a", "b", "c", "c", "c")) # 1 4

What's the best way to specify matches other than the first? For example, that we want the 2nd match for "a" and the 3rd for "c" (so we'd get: 2 6).

Update: the inefficient solution does n lookups:

value_index_query <- data.frame(value = c("a", "c"), index = c(2, 3))
id <-  c("a", "a", "b", "c", "c", "c")
apply(value_index_query, 1, function(value_index) {
  value <- value_index[1]
  index <- as.integer(value_index[2])
  which(id == value)[index]
})
like image 245
nachocab Avatar asked Dec 16 '15 23:12

nachocab


Video Answer


3 Answers

This also uses mapply to run the two columns in tandem through the which(.)[n] operation.

with(value_index_query,  
     mapply( function(target, nth) which(id==target)[nth], 
               target=value, nth=index) )
[1] 2 6
like image 160
IRTFM Avatar answered Oct 09 '22 13:10

IRTFM


Here is a data.table solution where we join the id vector with a mapping table. Then we can use .EACHI for the grouping, grabbing the index from .I for each group.

library(data.table)
## 'dti' would be your 'value_index_query' with the 'value' column renamed
dti <- data.table(id = c("a", "c"), index = c(2, 3))
## join it with 'id' and take 'index' by group
data.table(id)[dti, .I[index], by = .EACHI, on = "id"]$V1
# [1] 2 6

We can put that into a function:

viq <- function(id, value, index) {
    dti <- data.table(id = value, index = index)
    data.table(id)[dti, .I[index], by = .EACHI, on = "id"]$V1
}

id <- c("a", "a", "b", "c", "c", "c")

viq(id, c("a", "c"), 2:3)
# [1] 2 6
viq(id, c("a", "c"), c(2, 4))
# [1]  2 NA
viq(id, c("a", "b", "c"), c(2, 1, 4))
# [1]  2  3 NA
viq(id, c("a", "b", "c"), c(2, 1, 3))
# [1] 2 3 6
like image 40
Rich Scriven Avatar answered Oct 09 '22 13:10

Rich Scriven


One at a time with grep.

vec <- c("a", "a", "b", "c", "c", "c")
aa <-grep("a", vec)[2] #2nd
cc <-grep("c", vec)[3] #3rd
c(aa,cc)
#[1] 2 6
like image 44
Pierre Lapointe Avatar answered Oct 09 '22 14:10

Pierre Lapointe