Как экстраполировать за пределы точек x, переданных в "ksmooth"?


У меня есть такая функция ядра:

x <- 1:100
y <- rnorm(100, mean=(x/2000)^2)
plot(x,y)
kernel <- ksmooth(x,y, kernel="normal", bandwidth=10)
print(kernel$y)

Если я попытаюсь предсказать в точке вне диапазона значений x, это даст мне NaN, потому что он пытается экстраполировать за пределы данных:

x <- 1:100
y <- rnorm(100, mean=(x/2000)^2)
plot(x,y)
kernel <- ksmooth(x,y, kernel="normal", bandwidth=10, x.points=c(130))
print(kernel$y)

> print(kernel$y)
[1] NA

Даже когда я меняю range.x, он не сдвигается с места:

x <- 1:100
y <- rnorm(100, mean=(x/2000)^2)
plot(x,y)
kernel <- ksmooth(x,y, kernel="normal", bandwidth=10, range.x=c(1,200) , x.points=c(130))
print(kernel$y)

> print(kernel$y)
[1] NA

Как получить функцию ksmooth экстраполировать за пределы данных? Я знаю, что это плохая идея в теории, но на практике этот вопрос возникает все время.

1   5   2016-04-25 10:02:36

1 ответ:

Чтобы ответить на ваш побочный вопрос, взгляните на код ksmooth, range.x используется только тогда, когда x.points не предоставляется, так что объясняет, почему вы не видите его используемым. Давайте посмотрим на код в ksmooth:

function (x, y, kernel = c("box", "normal"), bandwidth = 0.5, 
    range.x = range(x), n.points = max(100L, length(x)), x.points) 
{
    if (missing(y) || is.null(y)) 
        stop("numeric y must be supplied.\nFor density estimation use density()")
    kernel <- match.arg(kernel)
    krn <- switch(kernel, box = 1L, normal = 2L)
    x.points <- if (missing(x.points)) 
        seq.int(range.x[1L], range.x[2L], length.out = n.points)
    else {
        n.points <- length(x.points)
        sort(x.points)
    }
    ord <- order(x)
    .Call(C_ksmooth, x[ord], y[ord], x.points, krn, bandwidth)
}
Из этого мы видим, что нам не нужно предоставлять x.points, чтобы убедиться, что range.x используется. Если вы бежите:
x <- 1:100
y <- rnorm(100, mean=(x/2000)^2)
plot(x,y)
kernel <- ksmooth(x,y, kernel="normal", bandwidth=10, range.x=c(1,200))
plot(kernel$x, kernel$y)

Теперь вы увидите, что ваше ядро оценивается выше 100 (хотя и не до 200). Увеличение параметра полосы пропускания позволяет еще дальше уйти от 100.