【问题标题】:Python/SciPy: How to get cubic spline equations from CubicSplinePython/SciPy:如何从 CubicSpline 获取三次样条方程
【发布时间】:2017-04-17 19:41:06
【问题描述】:

我正在通过一组给定的数据点生成三次样条曲线图:

import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate

x = np.array([1, 2, 4, 5])  # sort data points by increasing x value
y = np.array([2, 1, 4, 3])
arr = np.arange(np.amin(x), np.amax(x), 0.01)
s = interpolate.CubicSpline(x, y)
plt.plot(x, y, 'bo', label='Data Point')
plt.plot(arr, s(arr), 'r-', label='Cubic Spline')
plt.legend()
plt.show()

如何从CubicSpline 获得样条方程?我需要以下形式的方程:

我尝试了各种方法来获取系数,但它们都使用了使用不同数据获得的数据,而不仅仅是数据点。

【问题讨论】:

    标签: python numpy scipy spline


    【解决方案1】:

    来自the documentation

    c (ndarray, shape (4, n-1, ...)) 每个段上多项式的系数。尾随尺寸与y 的尺寸相匹配, 不包括轴。例如,如果 y 是 1-d,那么 c[k, i](x-x[i])**(3-k)x[i] 和之间的段上的系数 x[i+1].

    因此,在您的示例中,第一段 [x1, x2] 的系数将在第 0 列中:

    • y1 将是 s.c[3, 0]
    • b1 将是 s.c[2, 0]
    • c1 将是s.c[1, 0]
    • d1 将是 s.c[0, 0]

    那么对于第二段 [x2, x3] 你会得到s.c[3, 1], s.c[2, 1], s.c[1, 1] s.c[0, 1] 代表 y2b2c2d2,以此类推。

    例如:

    x = np.array([1, 2, 4, 5])  # sort data points by increasing x value
    y = np.array([2, 1, 4, 3])
    arr = np.arange(np.amin(x), np.amax(x), 0.01)
    s = interpolate.CubicSpline(x, y)
    
    fig, ax = plt.subplots(1, 1)
    ax.hold(True)
    ax.plot(x, y, 'bo', label='Data Point')
    ax.plot(arr, s(arr), 'k-', label='Cubic Spline', lw=1)
    
    for i in range(x.shape[0] - 1):
        segment_x = np.linspace(x[i], x[i + 1], 100)
        # A (4, 100) array, where the rows contain (x-x[i])**3, (x-x[i])**2 etc.
        exp_x = (segment_x - x[i])[None, :] ** np.arange(4)[::-1, None]
        # Sum over the rows of exp_x weighted by coefficients in the ith column of s.c
        segment_y = s.c[:, i].dot(exp_x)
        ax.plot(segment_x, segment_y, label='Segment {}'.format(i), ls='--', lw=3)
    
    ax.legend()
    plt.show()
    

    【讨论】:

      【解决方案2】:

      编辑:由于系数可以作为属性访问(请参阅@ali_m 的答案),此处显示的方法不必要地间接。如果有人使用更不透明的库偶然发现这个问题,我会把它留在网上。

      一种方法是在感兴趣的节点处进行评估:

      coeffs = [s(2)] + [s.derivative(i)(2) / misc.factorial(i) for i in range(1,4)]
      s(2.5)
      # -> array(1.59375)
      sum(coeffs[i]*(2.5-2)**i for i in range(4))
      # -> 1.59375
      

      严格来说,节点上不存在高阶导数,但 scipy 似乎返回右单向导数,因此即使它不应该也可以工作。

      【讨论】:

      • 我尝试用一​​个样本运行它,但系数的答案不正确。
      • @jshapy8 你愿意分享那个样本吗?在您发布的示例中,它似乎运行良好。
      • 在我发布的样本中,S_1 的系数应如下所示:2, (-13/8), 0, (5/8) on [1,2]
      • @jshapy8 我的方法和@ali_m 的方法得到了相同的系数。如果我在1.3 评估您的系数,比如说,我得到的结果与s(1.3) 不同。
      • @我不知道,可能不同的边界条件。您确实意识到系数取决于边界条件吗?你为什么不试试你的系数并在[1,2) 中的几个点上进行评估,然后在相同的点上评估s
      猜你喜欢
      • 2021-07-03
      • 1970-01-01
      • 2018-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-07
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多