Hel*_*ess 27 python interpolation linear-interpolation
我对编程很新,并且认为我会尝试编写线性插值函数.
说我给出的数据如下:
x = [1, 2.5, 3.4, 5.8, 6]
y = [2, 4, 5.8, 4.3, 4]
Run Code Online (Sandbox Code Playgroud)
我想设计一个函数,它将使用Python在1和2.5之间,2.5到3.4之间线性插值,依此类推.
我试过通过Python教程,但我仍然无法理解它.
Dav*_*ave 38
import scipy.interpolate
y_interp = scipy.interpolate.interp1d(x, y)
print y_interp(5.0)
Run Code Online (Sandbox Code Playgroud)
scipy.interpolate.interp1d 进行线性插值并可以自定义以处理错误情况.
car*_*ett 17
正如我理解你的问题,你想写一些函数y = interpolate(x_values, y_values, x),它会给你y一些价值x吗?然后基本思路遵循以下步骤:
x_values定义包含间隔的值的索引x.例如,对于x=3您的示例列表,包含的间隔将是[x1,x2]=[2.5,3.4],并且索引将是i1=1,i2=2 (y_values[i2]-y_values[i1])/(x_values[i2]-x_values[i1])(即dy/dx)计算此间隔的斜率.x现在是在值x1加上斜率乘以从距离x1.假设斜率与第一个/最后一个间隔相同,您还需要确定x在超出间隔的情况下会发生什么x_values,或者它是错误,或者您可以"向后"插值.
这有帮助,还是需要更具体的建议?
Lau*_*low 14
我想到了一个相当优雅的解决方案(恕我直言),所以我无法抗拒发布它:
from bisect import bisect_left
class Interpolate(object):
def __init__(self, x_list, y_list):
if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])):
raise ValueError("x_list must be in strictly ascending order!")
x_list = self.x_list = map(float, x_list)
y_list = self.y_list = map(float, y_list)
intervals = zip(x_list, x_list[1:], y_list, y_list[1:])
self.slopes = [(y2 - y1)/(x2 - x1) for x1, x2, y1, y2 in intervals]
def __getitem__(self, x):
i = bisect_left(self.x_list, x) - 1
return self.y_list[i] + self.slopes[i] * (x - self.x_list[i])
Run Code Online (Sandbox Code Playgroud)
我映射到float使整数除法(蟒蛇<= 2.7)都不会踢,毁灭的东西,如果x1,x2,y1和y2对于一些iterval所有整数.
在__getitem__我走的事实,self.x_list在使用升序排序的优势bisect_left,以(非常)快速找到最大元素小于的索引x中self.x_list.
使用这样的类:
i = Interpolate([1, 2.5, 3.4, 5.8, 6], [2, 4, 5.8, 4.3, 4])
# Get the interpolated value at x = 4:
y = i[4]
Run Code Online (Sandbox Code Playgroud)
为简单起见,我根本没有处理边境条件.因为它是,i[x]对于x < 1将作为如果线路工作从(2.5,4)至(1,2)已扩大到负无穷大,而i[x]用于x == 1或x > 6将引发IndexError.更好的是在所有情况下都会引发IndexError,但这仍然是读者的练习.:)
基于劳里茨的回答,这是一个具有以下更改的版本
__call__代替__getitem__from bisect import bisect_right
class Interpolate:
def __init__(self, x_list, y_list):
if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])):
raise ValueError("x_list must be in strictly ascending order!")
self.x_list = x_list
self.y_list = y_list
intervals = zip(x_list, x_list[1:], y_list, y_list[1:])
self.slopes = [(y2 - y1) / (x2 - x1) for x1, x2, y1, y2 in intervals]
def __call__(self, x):
if not (self.x_list[0] <= x <= self.x_list[-1]):
raise ValueError("x out of bounds!")
if x == self.x_list[-1]:
return self.y_list[-1]
i = bisect_right(self.x_list, x) - 1
return self.y_list[i] + self.slopes[i] * (x - self.x_list[i])
Run Code Online (Sandbox Code Playgroud)
用法示例:
>>> interp = Interpolate([1, 2.5, 3.4, 5.8, 6], [2, 4, 5.8, 4.3, 4])
>>> interp(4)
5.425
Run Code Online (Sandbox Code Playgroud)
小智 5
def interpolate(x1: float, x2: float, y1: float, y2: float, x: float):
"""Perform linear interpolation for x between (x1,y1) and (x2,y2) """
return ((y2 - y1) * x + x2 * y1 - x1 * y2) / (x2 - x1)
Run Code Online (Sandbox Code Playgroud)