欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python数据分析与挖掘实战---拉格朗日插值法

程序员文章站 2022-07-12 09:35:36
...

拉格朗日插值法

python数据分析与挖掘实战---拉格朗日插值法
python数据分析与挖掘实战---拉格朗日插值法

定义

对某个多项式函数,已知有给定的k + 1个取值点:
python数据分析与挖掘实战---拉格朗日插值法
其中Xj对应着自变量的位置,而Yj对应着函数在这个位置的取值。

假设任意两个不同的xj都互不相同,那么应用拉格朗日插值公式所得到的拉格朗日插值多项式为:
python数据分析与挖掘实战---拉格朗日插值法

其中每个python数据分析与挖掘实战---拉格朗日插值法

为拉格朗日基本多项式(或称插值基函数),其表达式为:

python数据分析与挖掘实战---拉格朗日插值法

拉格朗日基本多项式python数据分析与挖掘实战---拉格朗日插值法
的特点是在Xj上取值为1,在其它的点Xi,i≠j上取值为0。

范例

假设有某个二次多项式函数{\displaystyle f}f,已知它在三个点上的取值为:
python数据分析与挖掘实战---拉格朗日插值法
要求 f(18) 的值。

首先写出每个拉格朗日基本多项式:
python数据分析与挖掘实战---拉格朗日插值法
然后应用拉格朗日插值法,就可以得到{\displaystyle p}p的表达式({\displaystyle p}p为函数{\displaystyle f}f的插值函数):

python数据分析与挖掘实战---拉格朗日插值法

此时代入数值18就可以求出所需之值:
python数据分析与挖掘实战---拉格朗日插值法

源代码

import pandas as pd  # 导入数据分析库Pandas
from scipy.interpolate import lagrange  # 导入拉格朗日插值函数

inputfile = '../data/catering_sale.xls'  # 销量数据路径
outputfile = '../tmp/sales.xls'  # 输出数据路径

data = pd.read_excel(inputfile)  # 读入数据
data[u'销量'][(data[u'销量'] < 400) | (data[u'销量'] > 5000)] = None  # 过滤异常值,将其变为空值

# 自定义列向量插值函数
# s为列向量,n为被插值的位置,k为取前后的数据个数,默认为5
def ployinterp_column(s, n, k=5):
  y = s[list(range(n-k, n)) + list(range(n+1, n+1+k))]  # 取数
  y = y[y.notnull()]  # 剔除空值
  return lagrange(y.index, list(y))(n)  # 插值并返回插值结果

# 逐个元素判断是否需要插值
for i in data.columns:
  for j in range(len(data)):
    if (data[i].isnull())[j]:  # 如果为空即插值。
      data[i][j] = ployinterp_column(data[i], j)

data.to_excel(outputfile)  # 输出结果,写入文件

KeyError: ‘Passing list-likes to .loc or [] with any missing labels is no longer supported, see https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#deprecate-loc-reindex-listlike’

修改源代码

import pandas as pd  # 导入数据分析库Pandas
from scipy.interpolate import lagrange  # 导入拉格朗日插值函数

inputfile = '../data/catering_sale.xls'  # 销量数据路径
outputfile = '../tmp/sales.xls'  # 输出数据路径

data = pd.read_excel(inputfile)  # 读入数据
data.loc[((data['销量'] < 400) | (data['销量'] > 5000)), '销量'] = None  # 过滤异常值,将其变为空值

# 自定义列向量插值函数
# s为列向量,n为被插值的位置,k为取前后的数据个数,默认为5
def ployinterp_column(s, n, k=5):
  y = s.reindex((list(range(n-k, n)) + list(range(n+1, n+1+k)))  # 取数
  y = y[y.notnull()]  # 剔除空值
  return lagrange(y.index, list(y))(n)  # 插值并返回插值结果

# 逐个元素判断是否需要插值
for i in data.columns:
  for j in range(len(data)):
    if (data[i].isnull())[j]:  # 如果为空即插值。
      data.loc[j, i] = ployinterp_column(data[i], j)

data.to_excel(outputfile)  # 输出结果,写入文件

错误是传递了不存在标签的索引,上述代码

y = s[list(range(n-k, n)) + list(range(n+1, n+1+k))]

当n,也就是行索引在数据头或尾k个位置之内时会产生源数据不存在的行索引,0.21.0版本之前会为对应的索引建立NaN值,0.21.0版本之后会报错误

优点与缺点

拉格朗日插值法的公式结构整齐紧凑,在理论分析中十分方便,然而在计算中,当插值点增加或减少一个时,所对应的基本多项式就需要全部重新计算,于是整个公式都会变化,非常繁琐。这时可以用重心拉格朗日插值法或牛顿插值法来代替。此外,当插值点比较多的时候,拉格朗日插值多项式的次数可能会很高,因此具有数值不稳定的特点,也就是说尽管在已知的几个点取到给定的数值,但在附近却会和“实际上”的值之间有很大的偏差。这类现象也被称为龙格现象,解决的办法是分段用较低次数的插值多项式。