微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

提取样条整数 y 值的 x 值?

如何解决提取样条整数 y 值的 x 值?

我有给定的样本数据和插值样条:

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

x = [0.1,1.5,2.3,5.5,6.7,7]
y = [5,4,5,2,3]
s = interpolate.UnivariateSpline(x,y,s=0)

xs = np.linspace(min(x),max(x),10000) #values for x axis
ys = s(xs)

plt.figure()
plt.plot(xs,ys,label='spline')
plt.plot(x,'x',label='collected data')
plt.legend()

enter image description here

我想提取与样条的整数 y 值相对应的 x 值,但我不确定如何执行此操作。我假设我将使用 np.where() 并尝试过(无济于事):

root_index = np.where(ys == ys.round())

解决方法

equal 比较两个浮点数不是一个好主意。使用:

# play with `thresh`
thresh = 1e-4

root_index = np.where(np.abs(ys - ys.round())<1e-4)

printt(xs[root_index])
print(ys[root_index])

输出:

array([0.1,0.44779478,2.29993999,4.83732373,7.        ])
array([5.,4.00009501,4.99994831,3.00006626,3.        ])

Numpy 也有 np.isclose。所以像:

root_index = np.isclose(ys,ys.round(),rtol=1e-5,atol=1e-4)
ys[root_index]

你有相同的输出。

,

您可以使用 this post 中的 find_roots 函数来查找精确的插值 x 值:

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

def find_roots(x,y):
    s = np.abs(np.diff(np.sign(y))).astype(bool)
    return x[:-1][s] + np.diff(x)[s] / (np.abs(y[1:][s] / y[:-1][s]) + 1)

x = [0.1,1.5,2.3,5.5,6.7,7]
y = [5,4,5,2,3]
s = interpolate.UnivariateSpline(x,y,s=0)

xs = np.linspace(min(x),max(x),500)  # values for x axis
ys = s(xs)

plt.figure()
plt.plot(xs,ys,label='spline')

for y0 in range(0,7):
    r = find_roots(xs,ys - y0)
    if len(r) > 0:
        plt.scatter(r,np.repeat(y0,len(r)),label=f'y0 = {y0}')
        for ri in r:
            plt.text(ri,y0,f'  {ri:.3f}',ha='left',va='center')
plt.legend()
plt.xlim(min(x) - 0.2,max(x) + 1)
plt.show()

example plot

PS:x 的点数要少得多,例如xs = np.linspace(min(x),50),曲线看起来有点颠簸,插值会略有不同:

less points

,

scipy.interpolate.UnivariateSpline 返回的对象是一个关于 fitpack 插值例程的包装器。您可以使用 CubicSpline 类获得相同的插值:将 s = interpolation.UnivariateSpline(x,s=0) 替换为 s = interpolation.CubicSpline(x,y)。结果是一样的,你可以在最后的图中看到。

使用 CubicSpline 的优点是它返回一个 PPoly 对象,该对象具有有效的 rootssolve 方法。您可以使用它来计算具有整数偏移量的根。

要计算可能的整数范围,您可以将 derivative 方法与 roots 结合使用:

x_extrema = np.concatenate((x[:1],s.derivative().roots(),x[-1:]))
y_extrema = s(x_extrema)
i_min = np.ceil(y_extrema.min())
i_max = np.floor(y_extrema.max())

现在您可以计算偏移样条的根:

x_ints = [s.solve(i) for i in np.arange(i_min,i_max + 1)]
x_ints = np.concatenate(x_ints)
x_ints.sort()

以下是一些额外的绘图命令及其输出:

plt.figure()
plt.plot(xs,interpolate.UnivariateSpline(x,s=0)(xs),label='Original Spline')
plt.plot(xs,'r:',label='CubicSpline')
plt.plot(x,'x',label = 'Collected Data')

plt.plot(x_extrema,y_extrema,'s',label='Extrema')
plt.hlines([i_min,i_max],xs[0],xs[-1],label='Integer Limits')
plt.plot(x_ints,s(x_ints),'^',label='Integer Y')

plt.legend()

enter image description here

您可以验证数字:

>>> s(x_ints)
array([5.,4.,5.,3.,2.,5.])

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。