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]
})
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
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With