scipy.interpolate
的可用方法,以及 scipy 用户指南。然而,我不太清楚选择正确的方法。
BSpline
,
splprep
,
splrep
,
UnivariateSpline
,
interp1d
,
make_interp_spline
和
CubicSpline
?
根据文档,所有函数都通过一系列输入点计算一些多项式样条函数。我应该选择哪个功能? A) 三次样条和 3 阶 B 样条有什么区别? B)
splprep()
和 splrep()
有什么区别? C) 为什么 interp1d()
将被弃用?
我知道我在这里问不同的问题,但我不认为将问题分开有什么意义,因为我认为答案是相关的。
总而言之,我发现 scipy.interpolate 模块的组织有点混乱。我想也许我不是唯一有这种印象的人,这就是我向 SO 伸出援手的原因。
这就是我已经走了多远。下面是一些针对某些测试数据运行不同样条函数的代码。它创建了下图。
CublicSpline
和任何 B 样条方法,为什么最终会得到不同的结果?BSpline
和 splprep
的输出构造一个 splrep
对象,使得 splev()
和 BSpline()
的结果是等价的。这样,我们就可以将 splrep
和 splprep
的输出转换为 scipy.interpolate()
的面向对象接口。splrep
、UnivariateSpline
和 make_interp_spline
会产生相同的结果。在我的二维数据中,我需要针对每个有效的数据维度独立应用插值。便利函数 interp1d
也能产生相同的结果。相关SO问题:Linksplprep
和 splrep
似乎无关。即使我为每个数据轴独立计算 splprep
两次(参见 p0_new),结果看起来也会有所不同。我在文档中看到 splprep 计算 n 维曲线的 B 样条表示。但splrep
和splprep
应该没有关系吗?splprep
、splrep
和UnivariateSpline
有平滑参数,而其他插值器没有这样的参数。splrep
与 UnivariateSpline
配对。但是,我找不到 splprep
的匹配的面向对象对应项。有吗import numpy as np
from scipy.interpolate import *
import matplotlib.pyplot as plt
points = [[0, 0], [4, 4], [-1, 9], [-4, -1], [-1, -9], [4, -4], [0, 0]]
points = np.asarray(points)
n = 50
ts = np.linspace(0, 1, len(points))
ts_new = np.linspace(0, 1, n)
(t0_0,c0_0,k0_0), u = splprep(points[:,[0]].T, s=0, k=3)
(t0_1,c0_1,k0_1), u = splprep(points[:,[1]].T, s=0, k=3)
p0_new = np.r_[np.asarray(splev(ts_new, (t0_0,c0_0,k0_0))),
np.asarray(splev(ts_new, (t0_1,c0_1,k0_1))),
].T
# splprep/splev
(t1,c1,k1), u = splprep(points.T, s=0, k=3)
p1_new = splev(ts_new, (t1,c1,k1))
# BSpline from splprep
p2_new = BSpline(t1, np.asarray(c1).T, k=k1)(ts_new)
# splrep/splev (per dimension)
(t3_0,c3_0,k3_0) = splrep(ts, points[:,0].T, s=0, k=3)
(t3_1,c3_1,k3_1) = splrep(ts, points[:,1].T, s=0, k=3)
p3_new = np.c_[splev(ts_new, (t3_0,c3_0,k3_0)),
splev(ts_new, (t3_1,c3_1,k3_1)),
]
# Bspline from splrep
p4_new = np.c_[BSpline(t3_0, np.asarray(c3_0), k=k3_0)(ts_new),
BSpline(t3_1, np.asarray(c3_1), k=k3_1)(ts_new),
]
# UnivariateSpline
p5_new = np.c_[UnivariateSpline(ts, points[:,0], s=0, k=3)(ts_new),
UnivariateSpline(ts, points[:,1], s=0, k=3)(ts_new),]
# make_interp_spline
p6_new = make_interp_spline(ts, points, k=3)(ts_new)
# CubicSpline
p7_new = CubicSpline(ts, points, bc_type="clamped")(ts_new)
# interp1d
p8_new = interp1d(ts, points.T, kind="cubic")(ts_new).T
fig, ax = plt.subplots()
ax.plot(*points.T, "o-", label="Original points")
ax.plot(*p1_new, "o-", label="1: splprep/splev")
ax.plot(*p2_new.T, "x-", label="1: BSpline from splprep")
ax.plot(*p3_new.T, "o-", label="2: splrep/splev")
ax.plot(*p4_new.T, "x-", label="2: BSpline from splrep")
ax.plot(*p5_new.T, "*-", label="2: UnivariateSpline")
ax.plot(*p6_new.T, "+-", label="2: make_interp_spline")
ax.plot(*p7_new.T, "x-", label="3: CubicSpline")
#ax.plot(*p8_new.T, "k+-", label="3: interp1d")
#ax.plot(*p0_new.T, "k+-", label="3: CubicSpline")
ax.set_aspect("equal")
ax.grid("on")
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()
BSpline、splprep、splrep、UnivariateSpline、interp1d、make_interp_spline 和 CubicSpline 之间有什么区别?
a
BSpline
对象表示以节点 t
、系数 c
和度 k
表示的样条函数。它对数据一无所知x, y
。它是一个低级实现对象,与 PPoly
同等——将 PPoly 与 BSpline 视为基础的变化。
make_interp_spline
构造一条样条线 (BSpline
),它穿过数据 x
和 y
——它是一个 插值样条线,因此 spl(x) == y
。它可以处理批量数据:如果 y 是二维的,并且第二维的长度为 n
,则 make_interp_spline(x, y)
表示一堆函数 y_1(x), y_2(x), ..., y_n(x)
。
CubicSpline
类似,但更受限制:它只允许三次样条,k=3
。如果您需要从立方体切换到例如立方体线性插值,使用 make_interp_spline
,您只需在调用站点将 k=3
更改为 k=1
。 OTOH,CubicSpline
具有 BSpline 所没有的一些功能:例如寻根。它是一个 PPoly 实例,而不是 BSpline。
interp1d 并未被弃用,它是legacy。 interp1d 的一个有用部分是最近/上一个/下一个模式。其余的只是委托给 make_interp_spline,所以最好直接使用它。
splrep
在给定数据的情况下构造一个 smoothing 样条函数。平滑量由 s
参数控制,其中 s=0
是插值。它返回的不是 BSpline,而是 tck 元组(结、系数和度)。
splprep
以参数形式构造平滑样条曲线。那是 (x(u), y(u))
不是 y(x)
。还返回 tck 元组。
UnivariateSpline
相当于 splrep
。
请注意,
scipy.interpolate
已经有机增长。近四分之一个世纪以来,至少有四代开发人员。而splrep
、splprep
和UnivariateSpline
委托的FITPACK库是从20世纪80年代开始的。 CubicSpline
、BSpline
和 make_interp_spline
未使用 FITPACK。
所以在新代码中我个人会推荐
make_interp_spline
+ BSpline
;如果您只需要立方,CubicSpline
也可以。
但是,如果我使用 CublicSpline 和任何 B 样条方法,为什么最终会得到不同的结果?
边界条件。
make_interp_spline
和 CubicSpline
默认为 not-a-knot
,您可以更改它。
splrep
等人仅使用not-a-knot
。