set.seed(12345)
up <- seq(0,1,length.out=100)^3
down <- sqrt(seq(1,0,length.out=100))
x <- c(seq(0,1,length.out=length(up)),
seq(1,0, length.out=length(down)))
data <- data.frame(x=x, y=c(up,down),
measuredx=x + rnorm(length(x))*0.01,
measuredy=c(up,down) + rnorm(length(up)+length(down))*0.03)
Вместо сглаживания data$measuredy
непосредственно над data$measuredx
, сделайте два отдельных сглаживания, сглаживая каждое по переменной временной отметки. Затем объедините установленные значения из двух сглаживающих. Это общий способ сглаживания замкнутой кривой или петли. (См. Также вопросы и ответы: Сглаживание непрерывных 2D точек )
t <- seq_len(nrow(data) + 1)
xs <- smooth.spline(t, c(data$measuredx, data$measuredx[1]))$y
ys <- smooth.spline(t, c(data$measuredy, data$measuredy[1]))$y
with(data, plot(measuredx, measuredy))
lines(xs, ys)
Например,
c(data$measuredx, data$measuredx[1])
просто для того, чтобы последнее значение в векторе совпадало с первым, чтобы завершить цикл.
Кривая на самом деле не замкнута в нижнем левом углу, потому что smooth.spline
выполняет сглаживание, а не интерполяцию, поэтому даже если мы обеспечим, чтобы вектор данных завершал цикл, подобранный может не быть замкнутым. Практический обходной путь - использовать взвешенную регрессию, накладывая большой вес на это место, чтобы оно закрылось.
t <- seq_len(nrow(data) + 1)
w <- rep(1, length(t)) ## initially identical weight everywhere
w[c(1, length(w))] <- 100000 ## give heavy weight
xs <- smooth.spline(t, c(data$measuredx, data$measuredx[1]), w)$y
ys <- smooth.spline(t, c(data$measuredy, data$measuredy[1]), w)$y
with(data, plot(measuredx, measuredy), col = 8)
lines(xs, ys, lwd = 2)