CubicSpline#
- class scipy.interpolate.CubicSpline(x, y, axis=0, bc_type='not-a-knot', extrapolate=None)[源代码][源代码]#
三次样条数据插值器。
使用分段三次多项式插值数据,该多项式是两次连续可微的 [1]。结果表示为
PPoly
实例,其断点与给定数据匹配。- 参数:
- x类数组, 形状 (n,)
包含自变量值的一维数组。值必须是实数、有限且严格递增的顺序。
- yarray_like
包含因变量值的数组。它可以有任意数量的维度,但沿
axis``(见下文)的长度必须与 ``x
的长度匹配。值必须是有限的。- 轴int, 可选
假设 y 沿其变化的轴。这意味着对于
x[i]
,相应的值是np.take(y, i, axis=axis)
。默认值为 0。- bc_type字符串或2元组,可选
边界条件类型。每个区段上的多项式的所有系数需要由边界条件给出的两个附加方程来确定 [2]。
如果 bc_type 是一个字符串,那么指定的条件将应用于样条线的两端。可用的条件有:
‘not-a-knot’ (默认): 曲线端点的第一段和第二段是相同的多项式。在没有边界条件信息时,这是一个很好的默认选择。
‘periodic’: 假设插值函数是周期为
x[-1] - x[0]
的周期函数。y 的第一个和最后一个值必须相同:y[0] == y[-1]
。这种边界条件将导致y'[0] == y'[-1]
和y''[0] == y''[-1]
。‘clamped’: 曲线端点的第一次导数为零。假设一个1D的`y`,``bc_type=((1, 0.0), (1, 0.0))``是相同的条件。
‘natural’: 曲线端点的二阶导数为零。假设有一个一维的 y,
bc_type=((2, 0.0), (2, 0.0))
是相同的条件。
如果 bc_type 是一个 2 元组,第一个和第二个值将分别应用于曲线的起点和终点。元组的值可以是前面提到的字符串之一(除了 ‘periodic’),或者是元组 (order, deriv_values),允许在曲线端点指定任意导数:
order: 导数的阶数,1 或 2。
deriv_value: 包含导数值的类数组对象,形状必须与 y 相同,但不包括
axis
维度。例如,如果 y 是 1 维的,那么 deriv_value 必须是一个标量。如果 y 是 3 维的,形状为 (n0, n1, n2) 且 axis=2,那么 deriv_value 必须是 2 维的,形状为 (n0, n1)。
- 外推{bool, ‘周期性’, None}, 可选
如果是布尔值,决定是否基于第一个和最后一个区间对边界外的点进行外推,或者返回NaN。如果是’periodic’,则使用周期性外推。如果是None(默认),则``extrapolate`` 对于
bc_type='periodic'
设置为 ‘periodic’,否则设置为 True。
- 属性:
- xndarray, 形状 (n,)
断点。传递给构造函数的同一个
x
。- cndarray, 形状 (4, n-1, …)
每个段上的多项式的系数。尾随维度与 y 的维度匹配,不包括
axis
。例如,如果 y 是一维的,那么c[k, i]
是x[i]
和x[i+1]
之间段上的(x-x[i])**(3-k)
的系数。- 轴整数
插值轴。与传递给构造函数的轴相同。
方法
__call__
(x[, nu, extrapolate])评估分段多项式或其导数。
derivative
([nu])构建一个新的分段多项式,表示导数。
antiderivative
([nu])构建一个新的分段多项式,表示其反导数。
integrate
(a, b[, extrapolate])计算分段多项式的定积分。
roots
([discontinuity, extrapolate])找到分段多项式的实根。
参见
Akima1DInterpolator
Akima 一维插值器。
PchipInterpolator
PCHIP 1-D 单调三次插值器。
PPoly
分段多项式,根据系数和断点定义。
注释
参数 bc_type 和
extrapolate
独立工作,即前者仅控制样条的构建,后者仅控制评估。当边界条件为 ‘not-a-knot’ 且 n = 2 时,它被替换为第一个导数等于线性插值斜率的条件。当两个边界条件均为 ‘not-a-knot’ 且 n = 3 时,求解过程寻求通过给定点的抛物线。
当’not-a-knot’边界条件应用于两端时,生成的样条将与`splrep`(使用``s=0``)和`InterpolatedUnivariateSpline`返回的样条相同,但这两种方法使用的是B样条基表示。
Added in version 0.18.0.
参考文献
[1]Cubic Spline Interpolation 在 Wikiversity 上。
[2]Carl de Boor, “A Practical Guide to Splines”, Springer-Verlag, 1978.
示例
在这个例子中,使用三次样条插值一个采样的正弦波。你可以看到,样条的连续性属性对一阶和二阶导数是成立的,仅对三阶导数不成立。
>>> import numpy as np >>> from scipy.interpolate import CubicSpline >>> import matplotlib.pyplot as plt >>> x = np.arange(10) >>> y = np.sin(x) >>> cs = CubicSpline(x, y) >>> xs = np.arange(-0.5, 9.6, 0.1) >>> fig, ax = plt.subplots(figsize=(6.5, 4)) >>> ax.plot(x, y, 'o', label='data') >>> ax.plot(xs, np.sin(xs), label='true') >>> ax.plot(xs, cs(xs), label="S") >>> ax.plot(xs, cs(xs, 1), label="S'") >>> ax.plot(xs, cs(xs, 2), label="S''") >>> ax.plot(xs, cs(xs, 3), label="S'''") >>> ax.set_xlim(-0.5, 9.5) >>> ax.legend(loc='lower left', ncol=2) >>> plt.show()
在第二个例子中,单位圆通过样条曲线进行插值。使用了周期性边界条件。你可以看到,在周期点 (1, 0) 处,一阶导数值 ds/dx=0, ds/dy=1 被正确计算。注意,一个圆不能被三次样条曲线精确表示。为了提高精度,需要更多的断点。
>>> theta = 2 * np.pi * np.linspace(0, 1, 5) >>> y = np.c_[np.cos(theta), np.sin(theta)] >>> cs = CubicSpline(theta, y, bc_type='periodic') >>> print("ds/dx={:.1f} ds/dy={:.1f}".format(cs(0, 1)[0], cs(0, 1)[1])) ds/dx=0.0 ds/dy=1.0 >>> xs = 2 * np.pi * np.linspace(0, 1, 100) >>> fig, ax = plt.subplots(figsize=(6.5, 4)) >>> ax.plot(y[:, 0], y[:, 1], 'o', label='data') >>> ax.plot(np.cos(xs), np.sin(xs), label='true') >>> ax.plot(cs(xs)[:, 0], cs(xs)[:, 1], label='spline') >>> ax.axes.set_aspect('equal') >>> ax.legend(loc='center') >>> plt.show()
第三个例子是在区间 0 <= x <= 1 上对多项式 y = x**3 进行插值。三次样条可以精确地表示这个函数。为了实现这一点,我们需要在区间的端点指定值和一阶导数。注意 y’ = 3 * x**2,因此 y’(0) = 0 且 y’(1) = 3。
>>> cs = CubicSpline([0, 1], [0, 1], bc_type=((1, 0), (1, 3))) >>> x = np.linspace(0, 1) >>> np.allclose(x**3, cs(x)) True