我的目标是计算通过一组点的平滑轨迹,如下所示.我已经看过了scipy.interpolatescipy user guide的可用方法.然而,对我来说, Select 正确的方法并不是很清楚.

它们之间的区别是什么 BSplinesplprepsplrepUnivariateSplineinterp1dmake_interp_splineCubicSpline

根据文献,所有的函数都是通过一系列的输入点来计算某个多项式样条函数.我应该 Select 哪种功能?A)三次样条和三次B样条有什么不同?B)splprep()splrep()之间的区别是什么?C)为什么interp1d()将被弃用?

我知道我在这里问了不同的问题,但我看不出把问题分开的意义,因为我假设答案是相关的.

总而言之,我发现scipy.interpolate模块的组织有些混乱.我想也许我不是唯一一个有这种印象的人,这就是为什么我要向他们伸出援手.


这就是我所走的路.下面是对一些测试数据运行不同的样条线函数的一些代码.它创建了下图.

  1. 我在某处读到过:"所有的三次样条线都可以表示为3阶B-样条线","这是一个视角问题,哪种表示法更方便".但是,如果我使用CublicSpline和任何一种B样条法,为什么我会得到不同的结果?
  2. 我发现可以从splprepsplrep的输出构造一个BSpline对象,这样splev()BSpline()的结果是等价的.这样,我们就可以将splrepsplprep的输出转换为scipy.interpolate()的面向对象接口.
  3. splrepUnivariateSplinemake_interp_spline导致相同的结果.在我的2D数据中,我需要在每个数据维度上独立地应用插值.便利函数interp1d也产生相同的结果.相关SO问题:Link
  4. splprepsplrep似乎没有关系.即使我 for each 数据轴单独计算两次splprep(参见P0_NEW),结果看起来也不同.我在文档中看到,Splprep计算n-D曲线的B-Spline表示.但是,splrepsplprep是否应该没有关系呢?
  5. splprepsplrepUnivariateSpline具有平滑参数,而其他插值器没有此类参数.
  6. splrep双,UnivariateSpline双.然而,我找不到与splprep相匹配的面向对象的版本.有吗?

Comparison of different spline methods

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()

推荐答案

B Spline、Splprep、Splrep、UniariateSpline、Interp1d、make_interp_Spline和Cubi Spline之间有什么区别?

  • BSpline对象用 node t、系数c和阶数k表示样条线函数.它对数据x, y一无所知.它是一个低级实现对象,与PPoly不相上下-将PPoly与BSpline视为基础的变化.

  • make_interp_spline构造一条通过数据xy的样条线(BSpline)--这是一条interpolating样条线,所以spl(x) == y.它可以处理成批的数据:如果y是二维的,并且第二维的长度为n,则make_interp_spline(x, y)表示函数y_1(x), y_2(x), ..., y_n(x)的堆栈.

  • CubicSpline类似,但有更多限制:它只允许三次样条线k=3.如果您需要从三次曲线转换为线性插值法,只需在调用点将k=3改为k=1即可.OTOH,CubicSpline有一些BSpline没有的功能:例如寻根.它是PPoly实例,不是BSpline.

  • Interp1d不是弃用的,它是legacy.Interp1d的一个有用部分是最近/上一个/下一个模式.其余的只是委托给make_interp_样条线,所以最好直接使用它.

  • splrep构造了一个给定数据的smoothing样条函数.平滑量由s参数控制,其中s=0为内插.它返回的不是B样条线,而是tck元组( node 、系数和次数).

  • splprep以参数形式构造平滑样条曲线.(x(u), y(u))不是y(x)也返回tck-tuples.

  • UnivariateSpline等于splrep.

请注意,scipy.interpolate是有机增长的.在近四分之一个世纪里,至少有四代开发人员.而splrepsplprepUnivariateSpline代表的FITPACK库是从20世纪80年代开始的.CubicSplineBSplinemake_interp_spline未使用FITPACK.

所以在新的代码中,我个人推荐make_interp_spline + BSpline;如果你只需要立方,CubicSpline也可以.

但是,如果我使用CublicSpline和任何B-Spline方法,为什么我会得到不同的结果?

边界条件.make_interp_splineCubicSpline都默认为not-a-knot,您可以更改它. splrep等人只用了not-a-knot.

Python相关问答推荐

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

使用SciPy进行曲线匹配未能给出正确的匹配

使用索引列表列表对列进行切片并获取行方向的向量长度

如何在python polars中停止otherate(),当使用when()表达式时?

Pandas:将多级列名改为一级

Plotly Dash Creating Interactive Graph下拉列表

如何启动下载并在不击中磁盘的情况下呈现响应?

如何获取Python synsets列表的第一个内容?

Pandas:填充行并删除重复项,但保留不同的值

用SymPy在Python中求解指数函数

如果包含特定值,则筛选Groupby

BeautifulSoup:超过24个字符(从a到z)的迭代失败:降低了首次深入了解数据集的复杂性:

Django Table—如果项目是唯一的,则单行

我可以不带视频系统的pygame,只用于游戏手柄输入吗?''

如何根据一定条件生成段id

如何在表单中添加管理员风格的输入(PDF)

Numpy`astype(Int)`给出`np.int64`而不是`int`-怎么办?

Pandas:使列中的列表大小与另一列中的列表大小相同

如何通过特定导入在类中执行Python代码

基于2级列表的Pandas 切片3级多索引