R中的三次样条插值

时间:2011-11-24 10:51:18

标签: r plot spline cubic

我正在尝试在R中实现三次样条函数。我已经使用了R库中可用的样条曲线,smooth.spline和smooth.Pspline函数,但我对结果并不满意所以我想要通过“自制”样条函数说服自己关于结果的一致性。我已经计算了三次多项式的系数,但我不知道如何绘制结果......它们似乎是随机点。您可以在下面找到源代码。任何帮助将不胜感激。

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")
}

谢谢

1 个答案:

答案 0 :(得分:8)

好的,这里......

此处的“控制点”是您要评估三次样条曲线的点。因此返回的点数(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'值。 Hullo,这里有什么不对吗?它应该是返回长度(xx)值......

然后我想我发现了别的东西 - 你的'休息'将会从for循环中退出。你真正想要的是跳过那个我继续下一个,直到你找到与你的观点相关的那个:

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