R中的三次样条插值

发布于 2024-12-18 08:01:34 字数 1703 浏览 3 评论 0原文

我正在尝试在 R 中实现三次样条。我已经使用了 R 库中提供的 spline、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")
}

谢谢

I am trying an implementation of a cubic spline in R. I have already used the spline, smooth.spline and smooth.Pspline functions that are available in the R libraries but I am not that happy with the results so I want to convince myself about the consistency of the results by a "homemade" spline function. I have already computed the coefficients for the 3rd degree polynomials, but I am not sure how to plot the results..they seem random points. You can find the source code below. Any help would be appreciated.

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

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

书信已泛黄 2024-12-25 08:01:34

好的,这里...

您的“控制点”是您要评估三次样条的点。因此返回的点数 (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”个值。你好,这是怎么了?它应该返回 length(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)
}

Okay here goes...

Your 'control points' here are the points at which you are going to evaluate the cubic spline. So the number of points returned (yy) is the same length as xx. This made me spot something:

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]

 }

This is only computing 'n' values of yy. Hullo, whats wrong here? It should be returning length(xx) values...

Then I think I spotted something else - your 'break' is going to drop out of the for loop. What you really want is to skip that i and go on to the next one until you hit the one relevant to your point:

#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]

 }
}

This is inefficient because you are computing some yy[j] and dumping them next time round the loop, but no matter, it gets the job done.

Wrap this into a function, so you can play with it easily. My function 'myspline' takes x and y for data to fit, and an xx vector for prediction locations. I can do:

> xx=seq(35,48,len=100)
> yy = myspline(x,y,xx)
> plot(xx,yy,type="l")
> points(x,y)
> 

And I get a nice curve going through the (x,y) points. Except for the first point which it seems to miss and heads off to zero, so I suspect there's still an off-by-one error somewhere. Oh well. 99% done.

Here's the code:

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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文