我正在尝试在r中实现三次样条,我已经使用了样条,平滑。花键光滑。在R库中有可用的样条函数,但我对结果不太满意,所以我想通过"自制"样条函数来说服自己结果的一致性。我已经计算了三次多项式的系数,但我不确定如何绘制结果……它们似乎是随机的点。您可以在下面找到源代码。如有任何帮助,不胜感激。
x = c(35,36,39,42,45,48)
y = c(2.87671519825595, 4.04868309245341, 3.95202175000174,
3.87683188946186, 4.07739945984612, 2.16064840967985)
n = length(x)
#determine width of intervals
h=0
for (i in 1:(n-1)){
h[i] = (x[i+1] - x[i])
}
A = 0
B = 0
C = 0
D = 0
#determine the matrix influence coefficients for the natural spline
for (i in 2:(n-1)){
j = i-1
D[j] = 2*(h[i-1] + h[i])
A[j] = h[i]
B[j] = h[i-1]
}
#determine the constant matrix C
for (i in 2:(n-1)){
j = i-1
C[j] = 6*((y[i+1] - y[i]) / h[i] - (y[i] - y[i-1]) / h[i-1])
}
#maximum TDMA length
ntdma = n - 2
#tridiagonal matrix algorithm
#upper triangularization
R = 0
for (i in 2:ntdma){
R = B[i]/D[i-1]
D[i] = D[i] - R * A[i-1]
C[i] = C[i] - R * C[i-1]
}
#set the last C
C[ntdma] = C[ntdma] / D[ntdma]
#back substitute
for (i in (ntdma-1):1){
C[i] = (C[i] - A[i] * C[i+1]) / D[i]
}
#end of tdma
#switch from C to S
S = 0
for (i in 2:(n-1)){
j = i - 1
S[i] = C[j]
}
#end conditions
S[1] <- 0 -> S[n]
#Calculate cubic ai,bi,ci and di from S and h
for (i in 1:(n-1)){
A[i] = (S[i+ 1] - S[i]) / (6 * h[i])
B[i] = S[i] / 2
C[i] = (y[i+1] - y[i]) / h[i] - (2 * h[i] * S[i] + h[i] * S[i + 1]) / 6
D[i] = y[i]
}
#control points
xx = c(x[2],x[4])
yy = 0
#spline evaluation
for (j in 1:length(xx)){
for (i in 1:n){
if (xx[j]<=x[i]){
break
}
yy[i] = A[i]*(xx[j] - x[i])^3 + B[i]*(xx[j] - x[i])^2 + C[i]*(xx[j] - x[i]) + D[i]
}
points(x,yy ,col="blue")
}
谢谢
好了…
这里的"控制点"是要计算三次样条的点。因此返回的点数(yy)与xx的长度相同。这让我发现了一些东西:
for (j in 1:length(xx)){
for (i in 1:n){
if (xx[j]<=x[i]){
break
}
yy[i] = A[i]*(xx[j] - x[i])^3 + B[i]*(xx[j] - x[i])^2 + C[i]*(xx[j] - x[i]) + D[i]
}
这只计算yy的n个值。喂,怎么了?它应该返回长度(xx)的值…
然后我想我发现了别的东西-你的'break'将退出for循环。你真正想要的是跳过这个i,继续下一个,直到你找到与你的观点相关的那个:
#spline evaluation
for (j in 1:length(xx)){
for (i in 1:n){
if (xx[j]<=x[i]){
next
}
yy[j] = A[i]*(xx[j] - x[i])^3 + B[i]*(xx[j] - x[i])^2 + C[i]*(xx[j] - x[i]) + D[i]
}
}
这是低效的,因为你计算了一些yy[j],并在下次循环时将它们丢弃,但没关系,它完成了工作。
将其封装到一个函数中,以便您可以轻松地使用它。我的函数"myspline"接受x和y作为拟合数据,并接受xx向量作为预测位置。我可以:
> xx=seq(35,48,len=100)
> yy = myspline(x,y,xx)
> plot(xx,yy,type="l")
> points(x,y)
>
得到一条经过(x,y)点的曲线。除了第一个点,它似乎错过了,并朝着零前进,所以我怀疑在某个地方仍然有一个误差。哦。99%完成。
代码如下:
myspline <- function(x,y,xx){
n = length(x)
h=0;yy=0
#determine width of intervals
for (i in 1:(n-1)){
h[i] = (x[i+1] - x[i])
}
A = 0
B = 0
C = 0
D = 0
#determine the matrix influence coefficients for the natural spline
for (i in 2:(n-1)){
j = i-1
D[j] = 2*(h[i-1] + h[i])
A[j] = h[i]
B[j] = h[i-1]
}
#determine the constant matrix C
for (i in 2:(n-1)){
j = i-1
C[j] = 6*((y[i+1] - y[i]) / h[i] - (y[i] - y[i-1]) / h[i-1])
}
#maximum TDMA length
ntdma = n - 2
#tridiagonal matrix algorithm
#upper triangularization
R = 0
for (i in 2:ntdma){
R = B[i]/D[i-1]
D[i] = D[i] - R * A[i-1]
C[i] = C[i] - R * C[i-1]
}
#set the last C
C[ntdma] = C[ntdma] / D[ntdma]
#back substitute
for (i in (ntdma-1):1){
C[i] = (C[i] - A[i] * C[i+1]) / D[i]
}
#end of tdma
#switch from C to S
S = 0
for (i in 2:(n-1)){
j = i - 1
S[i] = C[j]
}
#end conditions
S[1] <- 0 -> S[n]
#Calculate cubic ai,bi,ci and di from S and h
for (i in 1:(n-1)){
A[i] = (S[i+ 1] - S[i]) / (6 * h[i])
B[i] = S[i] / 2
C[i] = (y[i+1] - y[i]) / h[i] - (2 * h[i] * S[i] + h[i] * S[i + 1]) / 6
D[i] = y[i]
}
#control points
#xx = seq(x[2],x[4],len=100)
#spline evaluation
for (j in 1:length(xx)){
for (i in 1:n){
if (xx[j]<=x[i]){
next
}
yy[j] = A[i]*(xx[j] - x[i])^3 + B[i]*(xx[j] - x[i])^2 + C[i]*(xx[j] - x[i]) + D[i]
}
}
return(yy)
}