Самый быстрый подход к интерполяции между несколькими строками

У меня есть пересечения и наклоны 14 разных линий, где y = Slope * x + Intercept. Линии более или менее параллельны следующим образом. Каждая строка представляет определенный класс.

   Intercept     Slope
1   8.787611 -3.435561
2   6.853230 -2.662021
3   6.660198 -2.584231
4   6.929856 -2.678694
5   6.637965 -2.572499
6   7.132044 -2.744441
7   7.233281 -2.802287
8   7.285169 -2.807539
9   7.207577 -2.772140
10  6.872071 -2.640098
11  6.778350 -2.612107
12  6.994820 -2.706729
13  6.947074 -2.690497
14  7.486870 -2.864093

Когда новые данные поступают как (x, y). Я хотел бы сделать две задачи:

1) Найдите, какая линия ближе всего к точке (например, «1», «4» или «8»).

2) Найдите интерполированное значение при x = 2,6. Это означает, что если точка расположена между двумя линиями, а линии имеют значения 0 и -0.05 для x = 2.6, то интерполированное значение будет в [-0.05, 0] пропорционально расстоянию точки от линий.

      x         y
1  2.545726 0.1512721
2  2.545726 0.1512721
3  2.545843 0.1512721
4  2.545994 0.1512721
5  2.546611 0.1512721
6  2.546769 0.1512721
7  2.546995 0.1416945
8  2.547269 0.1416945
9  2.548765 0.1416945
10 2.548996 0.1416945

Я рассматриваю возможность написания собственного кода и определения расстояния до новой точки из 14 строк, используя эту страницу Википедии и затем выбирая два минимальных расстояния линий выше и ниже точки (если точка не выше или ниже всех 14 линий), и пропорционально интерполировать. Однако я почти уверен, что это будет не самый быстрый способ, поскольку он не векторизован. Мне было интересно, есть ли более быстрый подход к этой задаче.


person ahoosh    schedule 10.04.2017    source источник
comment
Я не уверен в вашем определении ближайшего. Вы имеете в виду абсолютную разницу в y для данного x или вы имеете в виду отсортированное расстояние до любой точки на линии. Итак, для части 2 вы больше не используете только ближайшую линию? Вам нужны две ближайшие линии (одна выше и одна ниже)? Это должен быть желаемый результат, который вы включили? Есть ли причина, по которой они имеют разные значения x? Возможно, было бы полезно иметь четко проработанный пример.   -  person MrFlick    schedule 10.04.2017
comment
@MrFlick Под расстоянием от точки до линии я имею в виду длину воображаемой линии, проходящей через точку и перпендикулярной исходной линии. Желаемый результат — это средневзвешенное значение результатов двух ближайших линий к точке.   -  person ahoosh    schedule 11.04.2017


Ответы (1)


введите здесь описание изображения

lines <- read.table(textConnection("
   Intercept     Slope
1   8.787611 -3.435561
2   6.853230 -2.662021
3   6.660198 -2.584231
4   6.929856 -2.678694
5   6.637965 -2.572499
6   7.132044 -2.744441
7   7.233281 -2.802287
8   7.285169 -2.807539
9   7.207577 -2.772140
10  6.872071 -2.640098
11  6.778350 -2.612107
12  6.994820 -2.706729
13  6.947074 -2.690497
14  7.486870 -2.864093"))


points <- read.table(textConnection("
      x         y
1  2.545726 0.1512721
2  2.545726 0.1512721
3  2.545843 0.1512721
4  2.545994 0.1512721
5  2.546611 0.1512721
6  2.546769 0.1512721
7  2.546995 0.1416945
8  2.547269 0.1416945
9  2.548765 0.1416945
10 2.548996 0.1416945"))

cartDist <- function(lines, x, y) {
    with(lines, abs(Slope*x-y+Intercept)/sqrt(Slope^2+1))
}

interp_ys <- sapply(1:nrow(points), function(i) {
    x <- points$x[i]
    y <- points$y[i]
    dists <- cartDist(lines, x, y)
    dr <- rank(dists)
    wh <- which(dr %in% c(1,2))
    ys <- with(lines[wh,], Slope*2.6+Intercept)
    sum(((sum(dists[wh]) - dists[wh]) * ys))/sum(dists[wh]) #weighted average
})

plot(NA, ylim=c(-0.01,0.16), xlim=c(2.53,2.61), xlab="x", ylab="y", main="Interpolated points")
for(i in 1:nrow(lines)) {
    abline(b=lines$Slope[i], a=lines$Intercept[i], col="gray")
}
points(x=points$x, y=points$y, col="red")
points(x=rep(2.6, nrow(points)), y=interp_ys, col="blue")
segments(x0=rep(2.6, nrow(points)), y0=interp_ys, x1=points$x, y1=points$y, lty=2,col="black")
person thc    schedule 10.04.2017
comment
Это именно то, что я искал. Является ли этот подход более быстрым, чем модули интерполяции на основе Fortran или C++, такие как akima? - person ahoosh; 11.04.2017
comment
Нет, это не будет быстрее, чем C++. Вы также можете использовать многопоточность в приведенном выше коде, превратив sapply в mclapply. Но я подозреваю, что это будет достаточно быстро в однопоточном режиме. Насколько велик ваш реальный набор данных? - person thc; 11.04.2017