填充示例
import numpy as np
import pandas as pd
from sklearn.impute import KNNImputer
data = {
'A': [80, 90, np.nan, 95],
'B': [60, 65, 56,np.nan],
'C': [np.nan,57,80,78],
'D': [78,83,67,np.nan]
}
df = pd.DataFrame(data)
knn_imputer = KNNImputer(n_neighbors=2, weights='uniform')
numeric_df = df.select_dtypes(include=[np.number])
imputed_data = knn_imputer.fit_transform(numeric_df)
imputed_df = pd.DataFrame(imputed_data, columns=numeric_df.columns)
print(df)
print(imputed_df)
'''
A B C D
0 80.0 60.0 NaN 78.0
1 90.0 65.0 57.0 83.0
2 NaN 56.0 80.0 67.0
3 95.0 NaN 78.0 NaN
A B C D
0 80.0 60.0 68.5 78.0
1 90.0 65.0 57.0 83.0
2 87.5 56.0 80.0 67.0
3 95.0 58.0 78.0 72.5
'''
from sklearn.metrics.pairwise import nan_euclidean_distances
nan_euclidean_distances(df)
'''输出
array([[ 0. , 14.14213562, 16.55294536, 30. ],
[14.14213562, 0. , 33.9803865 , 30.52867504],
[16.55294536, 33.9803865 , 0. , 4. ],
[30. , 30.52867504, 4. , 0. ]])
'''
举例解析
X=df.values
X,nan_euclidean_distances(X)
'''输出
(array([[80., 60., nan, 78.],
[90., 65., 57., 83.],
[nan, 56., 80., 67.],
[95., nan, 78., nan]]),
array([[ 0. , 14.14213562, 16.55294536, 30. ],
[14.14213562, 0. , 33.9803865 , 30.52867504],
[16.55294536, 33.9803865 , 0. , 4. ],
[30. , 30.52867504, 4. , 0. ]]))
'''
nan_euclidean_distances(X)
会返回一个距离矩阵,其中的每个元素 [i, j] 表示样本 X[i] 和样本 X[j] 之间的距离。
由于我们使用的是同一个数组 X 作为输入,所以距离矩阵将是方阵,并且对角线上的元素表示每个样本与自身的距离(由于忽略了 NaN 值,这些值可能不为0)。- 举例解释:
先将df转成数组X来看,总共有四行,如X[0]为[80., 60., nan, 78.],X[0]与各行(共4行)距离为[ 0. , 14.14213562, 16.55294536, 30. ],
X[0]和X[1]距离计算:
4
3
(
(
80
−
90
)
2
+
(
60
−
65
)
2
+
(
78
−
83
)
2
)
=
10
2
\sqrt{\frac{4}{3}((80-90)^2 + (60-65)^2+ (78-83)^2)}=10\sqrt2
34((80−90)2+(60−65)2+(78−83)2)
=102
其中4是元素总数,3是除去缺失值的元素数。
n_neighbors=2时,X[0]除去本身距离0,与X[1]和X[2]最近。则将其中两行与X[0]缺失值同列的元素取均值:(X[1,2]+X[2,2])/2=68.5,则X[0,2]填充为68.5。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/3ec1acfb19d64939a648fa5ba1ee8dec.png)
参考链接
KNN缺失值的插补原理