2012-04-15 22 views
6

Mam dwa wektory z kilku tysięcy punktów, ale uogólnione tutaj:R: znajdź najbliższy indeks

A <- c(10, 20, 30, 40, 50) 
b <- c(13, 17, 20) 

Jak mogę uzyskać indeksy z A że są najbliższy do b? Oczekiwany wynik to c(1, 2, 2).

wiem, że findInterval może znaleźć pierwsze wystąpienie, a nie najbliższa, i jestem świadomy, że which.min(abs(b[2] - A)) jest coraz cieplej, ale nie mogę dowiedzieć się, jak wektorować go do pracy z długimi wektorów zarówno A i b.

Odpowiedz

11

Możesz po prostu wpisać kod w sapply. Myślę, że ma tę samą prędkość, co pętla for, więc nie jest technicznie wektoryzowany:

sapply(b,function(x)which.min(abs(x - A))) 
+3

Zwróć uwagę, że 'which.min()' zwraca tylko pierwsze dopasowanie. Mogą istnieć inne elementy, które są równie bliskie. –

11

FindInterval bardzo ci odpowiada. Po prostu trzeba wybierać między offset powraca i następny:

#returns the nearest occurence of x in vec 
nearest.vec <- function(x, vec) 
{ 
    smallCandidate <- findInterval(x, vec, all.inside=TRUE) 
    largeCandidate <- smallCandidate + 1 
    #nudge is TRUE if large candidate is nearer, FALSE otherwise 
    nudge <- 2 * x > vec[smallCandidate] + vec[largeCandidate] 
    return(smallCandidate + nudge) 
} 

nearest.vec(b,A) 

powroty (1,2,2), która powinna porównywalna FindInterval wydajności.

+0

Naprawdę przydatne, dziękuję. Jestem zaskoczony, że nie ma czegoś takiego w bazie. Co prawdopodobnie oznacza, że ​​jest i nie jestem tego świadomy ...! – Flyto

0

Oto rozwiązanie, które wykorzystuje często pomijaną funkcję R outer. Nie jestem pewien, czy to będzie lepsze, ale pozwoli uniknąć sapply.

A <- c(10, 20, 30, 40, 50) 
b <- c(13, 17, 20) 

dist <- abs(outer(A, b, '-')) 
result <- apply(dist, 2, which.min) 

# [1] 1 2 2 
Powiązane problemy