昨天的一篇文章中提到了数据清洗中涉及缺失值,可通过删除数据、填补空值以及无视等方式进行处理。在空值填补方面,可用平均值、众数、中位数、固定值或者临近值进行填补。
删除数据这种方式比较适用于缺失值较少的情况,但是如果数据集本来就比较小,删除这种方法就不是一个很好的选择了。下面介绍一种用简单建模的方式进行空缺值填补的方法——拉格朗日插值法。
一、原理
在网上搜索了以下,发现这位答主的答案解析得非常清晰,感谢!如何直观地理解拉格朗日插值法?www.zhihu.com
所谓得拉格朗日插值法,就是根据平面上具有n个观测值(无两点在一条直线上),那么一定能够求得通过这n个观测值的一条n-1阶曲线或多项式。
1)已知通过n个观测值的n-1阶多项式
2)将各个观测值
代入多项式可得:
……
看我上面贴得链接得那个解答:
可以从2阶的多项式递推出这个n-1阶的解答:
即:
3)将缺失值x带入公式可得到相关的插入值。
二、代码实现案例
我们仍然使用前一篇文章中提到的catering_sale数据集。
第一步:导入各种需要的包和库
import pandas as pd
import numpy as np
from scipy.interpolate import lagrange #scipy自带的拉格朗日插值函数
input_data = 'chapter3/demo/data/catering_sale.xls'
output_data = 'chapter3/demo/data/output_data.xls'
第二步:将超出预期范围的值设为null,编写循环函数检测空值
input_data = pd.read_excel(input_data)
input_data[(input_data[u'销量']>5000) | (input_data[u'销量']<400)][u'销量'] = None
def tianbu(s,n,k=5): #s代表数据集的某列,n代表需要插入值的横坐标,k设定为初始值5,即取插入值前后值的个数
y = s[list(range(n-k,n))+list(range(n+1,n+k+1))]
y = y[y.notnull()]
return lagrange(y.index,list(y))(n) #使用拉格朗日函数计算x对应的y值
for i in input_data.columns:
for j in range(len(input_data)):
if (input_data[i].isnull())[j]:
input_data[i][j] = tianbu(input_data[i],j)
input_data.to_excel(output_data) # 将修改后的数据集导入表格
三、总结
整体来说拉格朗日插值法是一种比较方便的处理异常值和填补空值的方法,但也存在一定的局限性:
在操作过程中发现拉格朗日插值法有时会导致负值的产生,特别是当首行出现空值的时候,调整k值可以适当地规避这种情况的发生。
另外拉格朗日插值法容易收到插入值增删的影响,当插值节点增减时,插值多项式就会发生变化,这样就造成了一定的不便。