「Scipy」样条插值在数据可视化中的运用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「Scipy」样条插值在数据可视化中的运用相关的知识,希望对你有一定的参考价值。
参考技术A好久没有更新文章了,学校的教材发下来了,作业一下就变多了。
首先,把最终效果放出来:
运用样条插值,即 B-Spline ,可以使你在图表中使用曲线连接离散数据(在插值法中,这些离散数据称为 节点 )
正如你在上面所看到的那样,在Python中插值非常简单, Scipy 中的 interpolate 为你提供了样条插值所需要的一系列函数。
import部分就不多说了,
这里首先定义了一系列节点,这里数据是随机的,
接下来,首先使用 linspace 为插值提供所需的x值, splrep 根据节点计算了样条曲线的参数,最后将其传递给 splev 计算插值后的结果。
你可能是抱着想要用曲线连接节点的目的来看这篇文章,但看到这里还没搞懂插值法是个什么玩意,那么接下来的内容就是在讲数学中的插值法,与Python和Scipy已无关联。
插值法,就是在给定的节点中作出合适的函数,使得这条曲线 经过每一个节点 ,这也就是为什么在数据可视化中使用插值而不是其他方法的原因,因为插值后仍然能够准确知道每一节点所对应的值。
那么,是不是节点越多,插值的准确性就越高呢?
貌似是这样,毕竟节点越多,对曲线的限制条件就越多,那准确性不久越高了。
但是呢,如果你使用多节点直接插值(不是在程序中插值,因为程序会使用分段样条插值),你就会发现,曲线在两段有明显的震荡,并且节点越多,震荡越明显、越大:
这种现象被称为 Tolmé Runge 现象( 龙格现象 ),描述的就是这一问题。对此的数学证明在知乎上有, 传送门 。
通过龙格现象,我们会发现,当节点数量趋向于无穷时,插值的误差会趋向于无穷大:
那么,如何避免这一情况呢,可以把我们原先的等距节点替换成Chebyshev节点,但是如果我们的离散数据确实等距,这一方法不好用,那么就可以才用分段插值,我们的程序对龙格现象也是这样处理的。
分段插值就是将高次多项式拆分成多个低次多项式,一般都拆分成三次多项式。
由于插值和拟合常常一起出现,所以这里也简单提一下拟合。
拟合是对你给出的离散数据,作出于数据 差距最小 的函数,另外,按照拟合的结果,拟合也分线性拟合和非线性拟合。
拟合与插值的差别就在于,插值必须过节点,但是拟合不需要,所以拟合曲线的整体效果会更好,也就是更平滑。
拟合一般都用在数据分析里,因为拟合曲线更能够看出整体的变化趋势嘛。
这篇文章写起来难度还是想当大,如果我的描述有问题的话,欢迎评论区留言。
前往我的博客查看本文
在Python / Numpy / Scipy中找到两个数组之间的插值交集
我正在寻找一种简单的方法来找到两个Numpy数组之间的插值交集。我知道如果我们有两个函数句柄而不是两个数组,就可以实现这一点,如使用Scipy或使用Sympy在this链接中所示。我想做同样的事情,但是给出了两个数组,特别是线性样条线之间的线性样条线。
例如,假设我们有两个数组,y_1
和y_2
,两者都是在xSupport
评估的。
import numpy as np
xSupport = np.array([0,1])
y_1 = np.array([0,2])
y_2 = np.array([1,0])
我正在寻找返回1/3
的函数,它是这两行之间交叉点的x值。在我的应用程序中,支持大于2,所以我正在寻找一种独立于数组长度的方法。
与ser的答案一样:
import numpy as np
x = np.array([0,1])
y1 = np.array([0,2])
y2 = np.array([1,0])
def solve(f,x):
s = np.sign(f)
z = np.where(s == 0)[0]
if z:
return z
else:
s = s[0:-1] + s[1:]
z = np.where(s == 0)[0]
return z
def interp(f,x,z):
m = (f[z+1] - f[z]) / (x[z+1] - x[z])
return x[z] - f[z]/m
f = y1-y2
z = solve(f,x)
ans = interp(f,x,z)
print(ans)
通过假设您找到零,然后对两个系列的差异执行函数,可以简化问题。首先,'solve'找到符号转换发生的位置(暗示零点出现在其间),然后'interp'执行线性插值以找到解决方案。
在Digitizing an analog signal,我创建了一个名为find_transition_times
的函数。您可以通过为y_1 - y_2
传递y
并为0
传递threshold
来使用该函数:
In [5]: xSupport = np.array([0,1])
...: y_1 = np.array([0,2])
...: y_2 = np.array([1,0])
...:
In [6]: find_transition_times(xSupport, y_1 - y_2, 0)
Out[6]: array([ 0.33333333])
以上是关于「Scipy」样条插值在数据可视化中的运用的主要内容,如果未能解决你的问题,请参考以下文章
数值分析中的样条函数:使用scipy.interpolate.splrep函数实现
在Python / Numpy / Scipy中找到两个数组之间的插值交集