Mam rozwiązanie problemu, który obejmuje zapętlanie i działa, ale czuję, że brakuje mi czegoś, co wymaga bardziej wydajnej implementacji. Problem: Mam numeryczną sekwencję wektorową i chcę zidentyfikować początkową pozycję (pozycje) w innym wektorze pierwszego wektora.Jak indeksować sekwencję wektorową w sekwencji wektorowej
To działa tak:
# helper function for matchSequence
# wraps a vector by removing the first n elements and padding end with NAs
wrapVector <- function(x, n) {
stopifnot(n <= length(x))
if (n == length(x))
return(rep(NA, n))
else
return(c(x[(n+1):length(x)], rep(NA, n)))
}
wrapVector(LETTERS[1:5], 1)
## [1] "B" "C" "D" "E" NA
wrapVector(LETTERS[1:5], 2)
## [1] "C" "D" "E" NA NA
# returns the starting index positions of the sequence found in a vector
matchSequence <- function(seq, vec) {
matches <- seq[1] == vec
if (length(seq) == 1) return(which(matches))
for (i in 2:length(seq)) {
matches <- cbind(matches, seq[i] == wrapVector(vec, i - 1))
}
which(rowSums(matches) == i)
}
myVector <- c(3, NA, 1, 2, 4, 1, 1, 2)
matchSequence(1:2, myVector)
## [1] 3 7
matchSequence(c(4, 1, 1), myVector)
## [1] 5
matchSequence(1:3, myVector)
## integer(0)
Czy istnieje lepszy sposób na wdrożenie matchSequence()
?
Dodany
„Better” tutaj może oznaczać stosując bardziej eleganckie metody nie myśleć, ale nawet lepiej, oznaczałoby szybciej. Spróbuj porównując rozwiązania:
set.seed(100)
myVector2 <- sample(c(NA, 1:4), size = 1000, replace = TRUE)
matchSequence(c(4, 1, 1), myVector2)
## [1] 12 48 91 120 252 491 499 590 697 771 865
microbenchmark::microbenchmark(matchSequence(c(4, 1, 1), myVector2))
## Unit: microseconds
## expr min lq mean median uq max naval
## matchSequence(c(4, 1, 1), myVector2) 154.346 160.7335 174.4533 166.2635 176.5845 300.453 100
Testowałem odpowiedzi. Twój jest 5 razy szybszy niż Josh; i 50 razy szybciej niż moje i howarda na twoim przykładzie. – Frank