反转插值以给出与所需插值函数值相关联的变量

时间:2017-11-14 00:53:47

标签: python scipy interpolation

我试图使用scipy的插值函数反转插值函数。假设我创建了一个插值函数,

import scipy.interpolate as interpolate
interpolatedfunction = interpolated.interp1d(xvariable,data,kind='cubic')

当我指定:

时,是否有一些函数可以找到x
interpolatedfunction(x) == a

换句话说,“我希望我的插值函数等于a; xvariable的值是多少,使得我的函数等于a?”

我很欣赏我可以通过一些数值方案来做到这一点,但有更直接的方法吗?如果插值函数在xvariable中是多值的,那该怎么办?

3 个答案:

答案 0 :(得分:7)

有专门的方法可以找到三次样条的根。最简单的用法是InterpolatedUnivariateSpline对象的.roots()方法:

spl = InterpolatedUnivariateSpline(x, y)
roots = spl.roots()

这可以找到所有的根而不只是一个,因为通用解算器(fsolvebrentqnewtonbisect等等。

x = np.arange(20)
y = np.cos(np.arange(20))
spl = InterpolatedUnivariateSpline(x, y)
print(spl.roots())

输出array([ 1.56669456, 4.71145244, 7.85321627, 10.99554642, 14.13792756, 17.28271674])

但是,您希望将样条曲线等同于某个任意数字a而不是0.一个选项是重建样条曲线(您不能只从中减去a):

solutions = InterpolatedUnivariateSpline(x, y - a).roots()

请注意,这些都不适用于interp1d返回的函数;它没有roots方法。对于该函数,使用诸如fsolve之类的通用方法是一种选择,但您一次只能获得一个根。在任何情况下,当有更强大的方法进行相同类型的插值时,为什么要使用interp1d作为三次样条线?

非面向对象的方式

可以直接从样条系数中减去a,而不是在从数据中减去a后重建样条曲线。这要求我们采用非面向对象的插值方法。具体来说,sproot接受由splrep准备的tck元组,如下所示:

tck = splrep(x, y, k=3, s=0)
tck_mod = (tck[0], tck[1] - a, tck[2])
solutions = sproot(tck_mod)    

我不确定弄乱tck是否值得在这里获得收益,因为无论如何,大部分计算时间都可能在根查找中。但是有其他选择是好的。

答案 1 :(得分:4)

创建插值函数interp_fn后,您可以通过函数的根找到x interp_fn(x) == a的值

interp_fn2 = lambda x: interp_fn(x) - a

有许多选项可以在scipy.optimize中找到根。例如,使用牛顿方法,初始值从10开始:

from scipy import optimize

optimize.newton(interp_fn2, 10)

实际示例

创建插值函数,然后找到fn(x) == 5

的根
import numpy as np
from scipy import interpolate, optimize

x = np.arange(10)
y = 1 + 6*np.arange(10) - np.arange(10)**2
y2 = 5*np.ones_like(x)
plt.scatter(x,y)
plt.plot(x,y)
plt.plot(x,y2,'k-')
plt.show()

Plot of f(x) and y=5

# create the interpolated function, and then the offset
# function used to find the roots

interp_fn = interpolate.interp1d(x, y, 'quadratic')
interp_fn2 = lambda x: interp_fn(x)-5

# to find the roots, we need to supply a starting value
# because there are more than 1 root in our range, we need 
# to supply multiple starting values.  They should be 
# fairly close to the actual root

root1, root2 = optimize.newton(interp_fn2, 1), optimize.newton(interp_fn2, 5)

root1, root2
# returns:
(0.76393202250021064, 5.2360679774997898)

答案 2 :(得分:0)

如果数据是单调的,您也可以尝试:

反函数= interpolated.interp1d(data,xvariable,kind ='cubic')