一、前言
对于含有缺失值的数据集,如果通过删除小部分记录达到既定的目标,那么删除含有缺失值的记录的方法是最有效的。然而,这种方法也有很多问题,删除缺失值的同时也会损失一定的信息,对于那些数据集较小的来说这是影响很大的。
所以可以对这些缺失值进行填充。
最简单的处理原则:
- 缺失值少于20%
连续变量使用均值或者中位数填补;
分类变量不需要填补,单算一类即可,或者用众数填补。
- 缺失值在20%-80%
填补方法同上;
另外每个有缺失值的变量生成一个指示哑变量,参与后续的建模。
- 缺失值大于80%
每个有缺失值的变量生成一个指示哑变量,参与后续的建模,原始变量不使用。
也可以用最近邻插补法,可以在数据集中寻找与该样本除掉缺失属性最相近的样本,用相似的样本的属性值代替,求相似度可以采用聚类方法。
其次还有回归方法和插值法,回归方法及时建立回归模型,用已有的数据训练模型然后再预测。
插值法就有朗日插值法和牛顿插值法,这里就介绍一下拉格朗日插值法。
二、理论知识
下面是拉格朗日函数:
f
(
x
)
=
∑
i
=
1
i
=
3
y
i
∗
∏
i
≠
j
1
≤
j
≤
3
x
−
x
j
x
i
−
x
j
f(x)=\sum_{i=1}^{i=3}y_i * \prod_{i\neq j}^{1\leq j \leq 3}\frac{x-x_j}{x_i-x_j}
f(x)=i=1∑i=3yi∗i=j∏1≤j≤3xi−xjx−xj
如何得到这个函数的,分为下面几步:
三个点 ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) (x_1,y_1),(x_2,y_2),(x_3,y_3) (x1,y1),(x2,y2),(x3,y3)可以确定一条二次多项式的函数。这需要把三个点带入多项式然后解出各个系数。
但是拉格朗日的这个解法就不一样了。
第一步构建了一个函数:
f
1
(
x
)
=
(
x
−
x
2
)
(
x
−
x
3
)
(
x
1
−
x
2
)
(
x
1
−
x
3
)
f_1(x)=\frac{(x-x_2)(x-x_3)}{(x_1-x_2)(x_1-x_3)}
f1(x)=(x1−x2)(x1−x3)(x−x2)(x−x3)
这个函数在
x
=
x
1
x=x_1
x=x1时,值为1;
x
=
x
2
x=x_2
x=x2时,值为0;
x
=
x
3
x=x_3
x=x3时,值为0。
同理分别构建:
f
2
(
x
)
=
(
x
−
x
1
)
(
x
−
x
3
)
(
x
2
−
x
1
)
(
x
2
−
x
3
)
f_2(x)=\frac{(x-x_1)(x-x_3)}{(x_2-x_1)(x_2-x_3)}
f2(x)=(x2−x1)(x2−x3)(x−x1)(x−x3)
这个函数在
x
=
x
2
x=x_2
x=x2时,值为1;
x
=
x
1
x=x_1
x=x1和
x
=
x
3
x=x_3
x=x3时,值为0。
f
3
(
x
)
=
(
x
−
x
1
)
(
x
−
x
2
)
(
x
3
−
x
1
)
(
x
3
−
x
2
)
f_3(x)=\frac{(x-x_1)(x-x_2)}{(x_3-x_1)(x_3-x_2)}
f3(x)=(x3−x1)(x3−x2)(x−x1)(x−x2)
这个函数在
x
=
x
3
x=x_3
x=x3时,值为1;在
x
=
x
1
x=x_1
x=x1和
x
=
x
2
x=x_2
x=x2时,值为0。
那么
f
(
x
)
f(x)
f(x)就可以写为:
f
(
x
)
=
y
1
f
1
(
x
)
+
y
2
f
2
(
x
)
+
y
3
f
3
(
x
)
f(x)=y_1f_1(x)+y_2f_2(x)+y_3f_3(x)
f(x)=y1f1(x)+y2f2(x)+y3f3(x)
写为:
f
i
(
x
)
=
∏
i
≠
j
1
≤
j
≤
3
(
x
−
x
j
)
(
x
i
−
x
j
)
f_i(x)=\prod_{i\neq j}^{1\leq j \leq 3}\frac{(x-x_j)}{(x_i-x_j)}
fi(x)=i=j∏1≤j≤3(xi−xj)(x−xj)
得到拉格朗日函数。
三、代码实现
from scipy.interpolate import lagrange
def lag_fill(df, i, k):
r = 0 if (i - k) < 0 else (i - k)
l = len(df.index) if (i + 1 + k) > len(df.index) else (i + 1 + k)
y = df.loc[list(range(r, i)) + list(range(i + 1, l))]
for j in y.index:
if y.isnull().loc[j]:
y.drop(index = j, inplace = True)
x = y.index
lag = lagrange(x.values, y.values)
return lag(i)
index = np.array(data['Age'][data['Age'].isnull()].index)
nums = []
for i in index:
num = int(lag_fill(data['Age'], i, 5))
nums.append(num)
df = data['Age'].copy()
index = np.array(df[df.isnull()].index) # 缺失值的索引
for i in range(len(index)):
df.loc[index[i]] = nums[i]
df.isnull().sum()
结果为:
0
最后替换一下:
data['Age'] = df
data['Age'].isnull().sum()