R: найти ближайший индекс

У меня есть два вектора с несколькими тысячами точек, но здесь они обобщены:

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

Как получить индексы A, ближайшие к b? Ожидаемый результат будет c(1, 2, 2).

Я знаю, что findInterval может найти только первое вхождение, а не ближайшее, и я знаю, что which.min(abs(b[2] - A)) становится теплее, но я не могу понять, как его векторизовать, чтобы он работал с длинными векторами как A, так и b.


person Mike T    schedule 15.04.2012    source источник


Ответы (3)


Вы можете просто поместить свой код в sapply. Я думаю, что это имеет ту же скорость, что и цикл for, поэтому технически не векторизован:

sapply(b,function(x)which.min(abs(x - A)))
person Sacha Epskamp    schedule 15.04.2012
comment
Обратите внимание, что which.min() возвращает только первое совпадение. Могут быть и другие элементы, которые одинаково близки. - person Sacha Epskamp; 15.04.2012

FindInterval очень близко подходит к вам. Вам просто нужно выбрать между возвращаемым смещением и следующим:

#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)

возвращает (1,2,2) и должен быть сравним с FindInterval по производительности.

person Robert Sugar    schedule 15.01.2013
comment
Действительно полезно, спасибо. Я удивлен, что в базе нет ничего, что можно было бы сделать. Что, вероятно, означает, что есть, и я не знаю об этом...! - person Flyto; 08.08.2013

Вот решение, в котором используется часто упускаемая из виду функция R outer. Не уверен, что он будет работать лучше, но он избегает 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
person jdobres    schedule 05.10.2017