现实世界的数据通常有缺失值。
数据可能由于未记录的观测、不正确或不一致的数据录入等原因而包含缺失值。
许多机器学习算法不支持带有缺失数据的数据。因此,处理缺失数据对于准确的数据分析和构建鲁棒的模型很重要。
在本教程中,您将学习如何使用Python处理机器学习的缺失数据。
具体来说,完成本教程后,您将了解
- 如何将无效或损坏的值标记为数据集中缺失。
- 如何从数据集中删除带有缺失数据的行。
- 如何在数据集中使用平均值填充缺失值。
- 如何使用KNN和迭代填充器等高级技术来填充缺失值。
- 如何将缺失性编码为特征以帮助进行预测。
立即开始您的项目,阅读我的新书 《机器学习数据准备》,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。
注意:本文档中的示例假设您已安装了最新版本的Python 3,并带有Pandas、NumPy和Scikit-Learn。特别是scikit-learn版本1.1或更高版本,以及Python 3.8或更高版本。如果您需要帮助设置环境,请参阅此教程。
- 更新 2018年3月:更改了数据集文件的链接。
- 更新 2019年12月:更新了数据集链接到GitHub版本。
- 更新 2020年5月:更新了代码示例以适应API更改。添加了参考文献。
- 更新 2023年11月:添加了关于KNN和迭代填充器以及将缺失性编码为特征的部分。更新了代码示例。

如何使用Python处理缺失值
照片来自 CoCreatr,部分权利保留。
概述
本教程分为9部分
- 糖尿病数据集:我们在此了解一个已知存在缺失值的数据集。
- 标记缺失值:我们在此学习如何标记数据集中的缺失值。
- 缺失值会导致问题:我们在此看到机器学习算法在包含缺失值时可能出现的故障。
- 删除带有缺失值的行:我们在此了解如何删除包含缺失值的行。
- 填充缺失值:我们在此用合理的值替换缺失值。
- 使用KNN填充器填充缺失值:我们在此学习如何使用K近邻填充缺失值。
- 使用迭代填充器填充缺失值:我们在此看到如何使用迭代填充来填充多个特征中的缺失值。
- 支持缺失值的算法:我们在此了解支持缺失值的算法。
- 使用MissingIndicator编码缺失性:我们在此学习如何对数据集中的缺失性进行编码。
首先,让我们看一下带有缺失值的样本数据集。
1. 糖尿病数据集
糖尿病数据集涉及在给定医疗详细信息的情况下,预测5年内糖尿病的发病。
这是一个二元(2类)分类问题。每个类别的观测数量不平衡。有768个观测,8个输入变量和1个输出变量。变量名称如下:
- 0. 怀孕次数。
- 1. 口服葡萄糖耐量试验2小时后的血浆葡萄糖浓度。
- 2. 舒张压(毫米汞柱)。
- 3. 肱三头肌皮褶厚度(毫米)。
- 4. 2小时血清胰岛素(微单位/毫升)。
- 5. 身体质量指数(体重kg /(身高m)^2)。
- 6. 糖尿病血统函数。
- 7. 年龄(岁)。
- 8. 类别变量(0或1)。
预测最常见类别的基线性能约为65%的分类准确率。最高结果可达约77%的分类准确率。
下面是前 5 行的样本。
|
1 2 3 4 5 6 |
6,148,72,35,0,33.6,0.627,50,1 1,85,66,29,0,26.6,0.351,31,0 8,183,64,0,0,23.3,0.672,32,1 1,89,66,23,94,28.1,0.167,21,0 0,137,40,35,168,43.1,2.288,33,1 ... |
此数据集已知包含缺失值。
具体来说,一些列存在缺失观测,这些缺失值被标记为零值。
我们可以通过这些列的定义和领域知识来证实这一点,例如,对于身体质量指数或血压来说,零值是无效的。
在此处下载数据集,并将其保存到当前工作目录中,文件名为pima-indians-diabetes.csv。
想开始学习数据准备吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
2. 标记缺失值
大多数数据都存在缺失值,并且数据集越大,缺失值的可能性就越大。
缺失数据在真实数据集中并不少见。实际上,至少有一个数据点缺失的概率随着数据集大小的增加而增加。
—— 第187页,《特征工程与选择》,2019年。
在本节中,我们将研究如何识别和标记缺失值。
我们可以使用图表和汇总统计信息来帮助识别缺失或损坏的数据。
我们可以将数据集加载为Pandas DataFrame,并打印每个属性的汇总统计信息。
|
1 2 3 4 5 6 |
# 加载并汇总数据集 from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 汇总数据集 print(dataset.describe()) |
运行此示例会产生以下输出
|
1 2 3 4 5 6 7 8 9 10 11 |
0 1 2 ... 6 7 8 count 768.000000 768.000000 768.000000 ... 768.000000 768.000000 768.000000 mean 3.845052 120.894531 69.105469 ... 0.471876 33.240885 0.348958 std 3.369578 31.972618 19.355807 ... 0.331329 11.760232 0.476951 min 0.000000 0.000000 0.000000 ... 0.078000 21.000000 0.000000 25% 1.000000 99.000000 62.000000 ... 0.243750 24.000000 0.000000 50% 3.000000 117.000000 72.000000 ... 0.372500 29.000000 0.000000 75% 6.000000 140.250000 80.000000 ... 0.626250 41.000000 1.000000 max 17.000000 199.000000 122.000000 ... 2.420000 81.000000 1.000000 [8 行 x 9 列] |
这很有用。
我们可以看到有些列的最小值是零(0)。在某些列中,零值没有意义,表示无效或缺失值。
缺失值通常由超出范围的条目指示;也许是数值字段中的负数(例如-1),该字段通常只为正数,或者数字字段中的0,该字段永远不可能是0。
—— 第62页,《数据挖掘:实用的机器学习工具与技术》,2016年。
具体来说,以下列具有无效的零最小值:
- 1:血浆葡萄糖浓度
- 2:舒张压
- 3:肱三头肌皮褶厚度
- 4:2小时血清胰岛素
- 5:身体质量指数
让我们通过查看原始数据来确认这一点,示例打印了数据的前20行。
|
1 2 3 4 5 6 |
# 加载数据集并查看行 from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 打印数据的前20行 print(dataset.head(20)) |
运行示例,我们可以清楚地看到第2、3、4和5列中有0值。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
0 1 2 3 4 5 6 7 8 0 6 148 72 35 0 33.6 0.627 50 1 1 1 85 66 29 0 26.6 0.351 31 0 2 8 183 64 0 0 23.3 0.672 32 1 3 1 89 66 23 94 28.1 0.167 21 0 4 0 137 40 35 168 43.1 2.288 33 1 5 5 116 74 0 0 25.6 0.201 30 0 6 3 78 50 32 88 31.0 0.248 26 1 7 10 115 0 0 0 35.3 0.134 29 0 8 2 197 70 45 543 30.5 0.158 53 1 9 8 125 96 0 0 0.0 0.232 54 1 10 4 110 92 0 0 37.6 0.191 30 0 11 10 168 74 0 0 38.0 0.537 34 1 12 10 139 80 0 0 27.1 1.441 57 0 13 1 189 60 23 846 30.1 0.398 59 1 14 5 166 72 19 175 25.8 0.587 51 1 15 7 100 0 0 0 30.0 0.484 32 1 16 0 118 84 47 230 45.8 0.551 31 1 17 7 107 74 0 0 29.6 0.254 31 1 18 1 103 30 38 83 43.3 0.183 33 0 19 1 115 70 30 96 34.6 0.529 32 1 |
我们可以计算这些列中缺失值的数量。我们可以通过将DataFrame子集中所有值为零的值标记为True来做到这一点。然后,我们可以计算每列True值的数量。
我们可以通过将DataFrame子集中所有值为零的值标记为True来做到这一点。然后,我们可以计算每列True值的数量。
|
1 2 3 4 5 6 7 8 |
# 汇总每变量缺失值数量的示例 from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 计算每列缺失值的数量 num_missing = (dataset[[1,2,3,4,5]] == 0).sum() # 报告结果 print(num_missing) |
运行示例会打印以下输出。
|
1 2 3 4 5 |
1 5 2 35 3 227 4 374 5 11 |
我们可以看到,第1、2和5列只有少数零值,而第3和第4列显示了更多的零值,接近一半的行。
这突出表明,不同的“缺失值”策略可能需要针对不同的列,例如,为了确保仍有足够的记录可用于训练预测模型。
当一个预测因子本质上是离散的时,缺失性可以直接编码到该预测因子中,就好像它是自然发生的类别一样。
—— 第197页,《特征工程与选择》,2019年。
在Python中,特别是Pandas、NumPy和Scikit-Learn,我们将缺失值标记为NaN。
值为NaN的值会被诸如sum、count等操作忽略。
我们可以使用Pandas DataFrame上的replace()函数轻松地将值标记为NaN,对我们感兴趣的列的子集进行操作。
在用NaN替换缺失值之前,最好通过运行dataset.dtypes来验证列是否包含有效的数值数据类型。
|
1 2 3 4 5 |
# 验证列的数据类型 from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) print(dataset.dtypes) |
我们看到所有列都是int或float。
|
1 2 3 4 5 6 7 8 9 10 |
0 int64 1 int64 2 int64 3 int64 4 int64 5 float64 6 float64 7 int64 8 int64 dtype: object |
标记了缺失值之后,我们可以使用isnull()函数将数据集中所有的NaN值标记为True,并获取每列的缺失值计数。
标记了缺失值之后,我们可以使用isnull()函数将数据集中所有的NaN值标记为True,并获取每列的缺失值计数。
|
1 2 3 4 5 6 7 8 9 |
# 标记缺失值为nan值的示例 from numpy import nan from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将'0'值替换为'nan' dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 计算每列NaN值的数量 print(dataset.isnull().sum()) |
运行示例会打印每列的缺失值数量。我们可以看到,第1到5列的缺失值数量与上面识别的零值数量相同。这表明我们已正确标记了已识别的缺失值。
我们可以看到,第1到5列的缺失值数量与上面识别的零值数量相同。这表明我们已正确标记了已识别的缺失值。
|
1 2 3 4 5 6 7 8 9 10 |
0 0 1 5 2 35 3 227 4 374 5 11 6 0 7 0 8 0 dtype: int64 |
这是一个有用的总结。但我还是喜欢查看实际数据,以确认我没有欺骗自己。
下面是相同的示例,只是我们打印了数据的前20行。
|
1 2 3 4 5 6 7 8 9 |
# 带有缺失值标记的数据集的查看行示例 from numpy import nan from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将'0'值替换为'nan' dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 打印数据的前20行 print(dataset.head(20)) |
运行示例,我们可以清楚地看到第2、3、4和5列中的NaN值。第1列只有5个缺失值,所以我们在前20行中没有看到示例并不奇怪。
从原始数据可以清楚地看出,标记缺失值已达到预期效果。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
0 1 2 3 4 5 6 7 8 0 6 148.0 72.0 35.0 NaN 33.6 0.627 50 1 1 1 85.0 66.0 29.0 NaN 26.6 0.351 31 0 2 8 183.0 64.0 NaN NaN 23.3 0.672 32 1 3 1 89.0 66.0 23.0 94.0 28.1 0.167 21 0 4 0 137.0 40.0 35.0 168.0 43.1 2.288 33 1 5 5 116.0 74.0 NaN NaN 25.6 0.201 30 0 6 3 78.0 50.0 32.0 88.0 31.0 0.248 26 1 7 10 115.0 NaN NaN NaN 35.3 0.134 29 0 8 2 197.0 70.0 45.0 543.0 30.5 0.158 53 1 9 8 125.0 96.0 NaN NaN NaN 0.232 54 1 10 4 110.0 92.0 NaN NaN 37.6 0.191 30 0 11 10 168.0 74.0 NaN NaN 38.0 0.537 34 1 12 10 139.0 80.0 NaN NaN 27.1 1.441 57 0 13 1 189.0 60.0 23.0 846.0 30.1 0.398 59 1 14 5 166.0 72.0 19.0 175.0 25.8 0.587 51 1 15 7 100.0 NaN NaN NaN 30.0 0.484 32 1 16 0 118.0 84.0 47.0 230.0 45.8 0.551 31 1 17 7 107.0 74.0 NaN NaN 29.6 0.254 31 1 18 1 103.0 30.0 38.0 83.0 43.3 0.183 33 0 19 1 115.0 70.0 30.0 96.0 34.6 0.529 32 1 |
在研究处理缺失值的方法之前,让我们先演示一下数据集中存在缺失值可能会导致问题。
3. 缺失值会导致问题
数据集中存在缺失值可能导致某些机器学习算法出现错误。
缺失值是常见的数据现象。不幸的是,大多数预测建模技术都无法处理任何缺失值。因此,这个问题必须在建模之前解决。
—— 第203页,《特征工程与选择》,2019年。
在本节中,我们将尝试在带有缺失值的数据集上评估线性判别分析(LDA)算法。
这是一种在数据集中存在缺失值时无法正常工作的算法。
以下示例在上一节中一样标记了数据集中的缺失值,然后尝试使用3折交叉验证来评估LDA并打印平均准确率。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 缺失值导致错误的示例 from numpy import nan from pandas import read_csv from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将'0'值替换为'nan' dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 将数据集分割为输入和输出 values = dataset.values X = values[:,0:8] y = values[:,8] # 定义模型 model = LinearDiscriminantAnalysis() # 定义模型评估程序 cv = KFold(n_splits=3, shuffle=True, random_state=1) # 评估模型 result = cross_val_score(model, X, y, cv=cv, scoring='accuracy') # 报告平均性能 print(f'Accuracy: {result.mean():.3f}') |
运行示例会导致错误,如下所示:
|
1 |
ValueError: Input contains NaN, infinity or a value too large for dtype('float64'). |
正如我们所预期的。
我们无法在带有缺失值的数据集上评估LDA算法(以及其他算法)。
许多流行的预测模型,如支持向量机、glmnet 和神经网络,都无法容忍任何缺失值。
—— 第195页,《特征工程与选择》,2019年。
现在,我们可以研究处理缺失值的方法了。
4. 删除带有缺失值的行
处理缺失数据的最简单策略是删除包含缺失值的记录。
处理缺失值最简单的方法是删除包含缺失值的整个预测因子和/或样本。
—— 第196页,《特征工程与选择》,2019年。
我们可以通过创建一个新的Pandas DataFrame来删除包含缺失值的行。
Pandas提供了dropna()函数,可用于删除带有缺失数据的列或行。我们可以使用dropna()删除所有包含缺失数据的行,如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 删除包含缺失值的行的示例 from numpy import nan from pandas import read_csv # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 汇总原始数据的形状 print(dataset.shape) # 将'0'值替换为'nan' dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 删除带有缺失值的行 dataset.dropna(inplace=True) # 汇总删除缺失行后数据的形状 print(dataset.shape) |
运行此示例,我们可以看到原始数据集中有768行,而删除所有包含NaN的行后减少到392行。
|
1 2 |
(768, 9) (392, 9) |
现在我们有了可以用来评估对缺失值敏感的算法(如LDA)的数据集。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# 评估删除缺失数据行后的模型 from numpy import nan from pandas import read_csv from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将'0'值替换为'nan' dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 删除带有缺失值的行 dataset.dropna(inplace=True) # 将数据集分割为输入和输出 values = dataset.values X = values[:,0:8] y = values[:,8] # 定义模型 model = LinearDiscriminantAnalysis() # 定义模型评估程序 cv = KFold(n_splits=3, shuffle=True, random_state=1) # 评估模型 result = cross_val_score(model, X, y, cv=cv, scoring='accuracy') # 报告平均性能 print(f'Accuracy: {result.mean():.3f}') |
注意:您的结果可能会因算法或评估程序的随机性,或数值精度的差异而有所不同。考虑运行示例几次并比较平均结果。
该示例成功运行并打印了模型的准确率。
|
1 |
Accuracy: 0.781 |
在某些预测建模问题中,删除带有缺失值的行可能会过于局限,另一种选择是填充缺失值。
5. 填充缺失值
填充是指使用模型来替换缺失值。
… 缺失数据可以被填充。在这种情况下,我们可以使用训练集预测因子中的信息来,实质上,估计其他预测因子的值。
— 第42页,《应用预测建模》,2013年。
我们可以考虑许多选项来替换缺失值,例如:
- 在域内有意义的常量值,例如0,与其他所有值不同。
- 来自另一个随机选择的记录的值。
- 列的平均值、中位数或众数。
- 由另一个预测模型估计的值。
在训练数据集上进行的任何填充都必须在未来需要从最终模型进行预测的新数据上进行。选择如何填充缺失值时需要考虑这一点。
例如,如果您选择使用列的平均值进行填充,则这些列的平均值需要存储到文件中,以供将来对具有缺失值的新数据使用。
Pandas提供了fillna()函数用于将缺失值替换为指定值。
例如,我们可以使用fillna()将缺失值替换为每列的平均值,如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 |
# 使用numpy手动填充缺失值 from pandas import read_csv from numpy import nan # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 使用列的平均值填充缺失值 dataset.fillna(dataset.mean(), inplace=True) # 计算每列NaN值的数量 print(dataset.isnull().sum()) |
运行示例会提供每列缺失值的计数,显示零缺失值。
|
1 2 3 4 5 6 7 8 9 10 |
0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 dtype: int64 |
scikit-learn库提供了SimpleImputer 预处理类,可用于替换缺失值。
它是一个灵活的类,允许您指定要替换的值(它可以是NaN以外的其他值)以及用于替换它的技术(例如平均值、中位数或众数)。SimpleImputer类直接在NumPy数组上操作,而不是在DataFrame上。
下面的示例使用SimpleImputer类将缺失值替换为每列的平均值,然后打印转换后矩阵中的NaN值数量。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 使用scikit-learn填充缺失值的示例 from numpy import nan from numpy import isnan from pandas import read_csv from sklearn.impute import SimpleImputer # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 检索 numpy 数组 values = dataset.values # 定义填充器 imputer = SimpleImputer(missing_values=nan, strategy='mean') # 转换数据集 transformed_values = imputer.fit_transform(values) # 计算每列NaN值的数量 print(f'Missing: {isnan(transformed_values).sum()}') |
运行示例显示所有NaN值都已成功填充。
|
1 |
缺失:0 |
6. 使用KNN填充器填充缺失值
到目前为止,我们已经看到了使用pandas fillna()方法和scikit-learn的SimpleImputer的简单填充策略。
KNN或K近邻填充是处理缺失值的另一种技术。您可以使用scikit-learn的KNNImputer来执行此填充。
对于具有缺失值的数据点,此技术在选定的距离度量(默认为欧几里得)下识别K个最近的点。最近点的数量或邻居由n_neighbors参数指定。默认情况下,考虑5个最近的邻居。
考虑一个具有缺失值的特征。缺失值是K个最近邻的该特征值的平均值,默认情况下均匀加权。
下面的示例使用n_neighbors设置为4的KNNImputer类,使用最近邻算法填充缺失值。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 使用KNN填充器填充缺失值的示例 from numpy import nan from numpy import isnan from pandas import read_csv from sklearn.impute import KNNImputer # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 检索 numpy 数组 values = dataset.values # 定义填充器 imputer = KNNImputer(n_neighbors=4) # 转换数据集 transformed_values = imputer.fit_transform(values) # 计算每列NaN值的数量 print(f'Missing: {isnan(transformed_values).sum()}') |
您会发现所有缺失值都已按预期填充。
|
1 |
Missing: 0 |
这里我们使用n_neighbors设置为4的KNN Imputer来填充数据集中缺失的值。为避免数据泄露,我们在管道中将KNN Imputer与LDA分类器一起使用,以便Imputer仅在训练数据集的样本上进行拟合。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# 在KNN填充器转换后评估模型的示例 from numpy import nan from pandas import read_csv from sklearn.pipeline import Pipeline from sklearn.impute import KNNImputer from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 将数据集分割为输入和输出 values = dataset.values X = values[:,0:8] y = values[:,8] # 定义填充器 imputer = KNNImputer(n_neighbors=4) # 定义模型 lda = LinearDiscriminantAnalysis() # 定义建模管道 pipeline = Pipeline(steps=[('imputer', imputer),('model', lda)]) # 定义交叉验证过程 kfold = KFold(n_splits=3, shuffle=True, random_state=1) # 评估模型 result = cross_val_score(pipeline, X, y, cv=kfold, scoring='accuracy') # 报告平均性能 print(f'Accuracy: {result.mean():.3f}') |
运行代码时,您应该会看到类似的输出。
|
1 |
Accuracy: 0.763 |
要详细了解KNN填充,请参阅此教程
7. 使用迭代填充器填充缺失值
Scikit-learn的IterativeImputer是一种更复杂的多变量填充技术。
IterativeImputer通过将一个特征建模为其他特征的函数来预测该特征的缺失值。因此,填充器使用其他特征作为预测因子来预测一个特征的缺失值。
然后,它以轮询方式填充所有缺失的特征。此填充过程会迭代max_iter次,默认为10次。
由于IterativeImputer功能仍处于实验阶段,您需要显式启用它。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 使用迭代填充器填充缺失值的示例 import numpy as np from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 检索 numpy 数组 values = dataset.values # 定义填充器 imputer = IterativeImputer(random_state=0) # 转换数据集 transformed_values = imputer.fit_transform(values) # 计算每列NaN值的数量 print(f'Missing: {isnan(transformed_values).sum()}') |
我们可以看到所有缺失值都已填充,没有缺失值。
|
1 |
Missing: 0 |
与之前的示例一样,我们可以通过创建包含迭代填充器和LDA模型的管道来在数据集上拟合LDA模型。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# 在迭代填充器转换后评估模型的示例 from numpy import nan from pandas import read_csv from sklearn.pipeline import Pipeline from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 将数据集分割为输入和输出 values = dataset.values X = values[:,0:8] y = values[:,8] # 定义填充器 imputer = IterativeImputer(random_state=1) # 定义模型 lda = LinearDiscriminantAnalysis() # 定义建模管道 pipeline = Pipeline(steps=[('imputer', imputer),('model', lda)]) # 定义交叉验证过程 kfold = KFold(n_splits=3, shuffle=True, random_state=1) # 评估模型 result = cross_val_score(pipeline, X, y, cv=kfold, scoring='accuracy') # 报告平均性能 print(f'Accuracy: {result.mean():.3f}') |
运行此示例应该会给您类似的输出。
|
1 |
Accuracy: 0.760 |
要了解有关迭代填充的更多信息,请参阅以下教程
8. 支持缺失值的算法
并非所有算法在数据缺失时都会失败。
有些算法可以处理缺失数据,例如k-近邻算法可以在距离度量中忽略缺失值的列。朴素贝叶斯在进行预测时也可以支持缺失值。
朴素贝叶斯一个真正的好处是,缺失值根本不是问题。
—— 第100页,《数据挖掘:实用的机器学习工具与技术》,2016年。
还有一些算法可以在构建预测模型时使用缺失值作为唯一且不同的值,例如分类和回归树。
… 一些预测模型,尤其是基于树的技术,可以专门处理缺失数据。
— 第42页,《应用预测建模》,2013年。
Boosting估计器(如梯度提升分类器)的scikit-learn实现原生支持缺失值。然而,朴素贝叶斯、决策树和k-近邻的scikit-learn实现对缺失值不健壮。尽管这一点正在考虑中。
尽管如此,如果您考虑使用其他算法实现(如xgboost)或开发自己的实现,这仍然是一个选项。
9. 使用MissingIndicator编码缺失性
Scikit-learn的Impute模块还提供了一个MissingIndicator类,用于在数据集中创建缺失值的二进制指示符。
使用指示符标记缺失值有助于以下方面:
- 理解数据中的缺失模式。
- 指导不同特征的填充策略。
- 创建指示特定特征值是否存在的新特征。
以下示例显示了如何使用MissingIndicator标记缺失值并获得二进制指示符矩阵。features参数默认设置为“missing-only”,以仅包含具有缺失值的特征列。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 使用缺失指示符的示例 from numpy import nan from numpy import isnan from pandas import read_csv from sklearn.impute import MissingIndicator # 加载数据集 dataset = read_csv('pima-indians-diabetes.csv', header=None) # 将零值标记为缺失或NaN dataset[[1,2,3,4,5]] = dataset[[1,2,3,4,5]].replace(0, nan) # 检索 numpy 数组 values = dataset.values # 实例化指示符 indicator = MissingIndicator(features="missing-only", error_on_new=True) # 转换数据集 indicators = indicator.fit_transform(values) # 计算每列NaN值的数量 print(f'Missing Indicators: \n{indicators}') |
这是输出的指示符矩阵,True表示缺失值,False表示存在值。
|
1 2 3 4 5 6 7 8 |
Missing Indicators: [[False False False True False] [False False False True False] [False False True True False] ... [False False False False False] [False False True True False] [False False False True False]] |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
相关教程
书籍
- 特征工程与选择, 2019.
- 《数据挖掘:实用机器学习工具与技术》(Data Mining: Practical Machine Learning Tools and Techniques), 2016.
- 特征工程与选择, 2019.
- 应用预测建模, 2013.
API
总结
在本教程中,您了解了如何处理包含缺失值的机器学习数据。
具体来说,你学到了:
- 如何将数据集中的缺失值标记为numpy.nan。
- 如何从数据集中删除包含缺失值的行。
- 如何用合理的值替换缺失值。
- 如何使用KNN和迭代填充技术填充缺失值。
您对处理缺失值有什么问题吗?
在评论中提出您的问题,我将尽力回答。







Fancy impute是我用来填充的库
https://github.com/hammerlab/fancyimpute
missingno 对于可视化也很棒!
https://github.com/ResidentMario/missingno
谢谢你的建议,Mike。
您好,朋友,我需要那个数据集“Pima-Indians-diabetes.csv”,我该如何访问它。它在这个网站上不可用。
所有数据集都在这里
https://github.com/jbrownlee/Datasets
谢谢,Jason。
不客气。
你好,
我有一个包含30万行和278列的数据集。我使用了MissForest来填充缺失值。但是,系统(HP Pavilion Intel i5,12GB RAM)运行了很长时间仍未完成。您有什么简单的方法建议吗?
我需要使用循环吗?
也许使用较少的数据?
也许在一个更快的机器上拟合?
在下面的链接中输入糖尿病数据集
https://datasetsearch.research.google.com/
请告诉我如何使用一个数据集填充中位数。
请告诉我,如果使用Fancy impute库,如何为X_test进行预测?
感谢指出这个有趣的问题。我很想再写一篇关于如何处理Python中的分类属性的文章。
亲爱的读者,请永远不要删除带有缺失值的行。这会改变数据的分布,您的分析可能会变得毫无价值。从别人的错误中学习,不要重复它们:)
谢谢,Jozo。
这篇帖子将有助于处理分类输入数据。
https://machinelearning.org.cn/data-preparation-gradient-boosting-xgboost-python/
超级棒!感谢您的撰写!是否值得提及Pandas的插值? https://pandas.ac.cn/pandas-docs/stable/generated/pandas.Series.interpolate.html
谢谢,Tommy。
嗨,Jason,
我只是在想,是否有办法为每列使用不同的填充策略?例如,对于分类特征,您希望使用众数进行填充,但对于连续属性,您希望使用平均值进行填充。
是的,尝试多种技术,选择结果最准确的模型。
谢谢您的教程,先生。
如果可能,我还会向您寻求关于文本数据的多标签分类的帮助。
例如,将推文分类为与体育、商业、科技或其它相关。
当然,请看这篇帖子
https://machinelearning.org.cn/sequence-classification-lstm-recurrent-neural-networks-python-keras/
布朗利先生您好。非常感谢您的帖子。
您是否知道任何识别缺失数据模式的方法?我的意思是,我对他系时间序列数据中的缺失数据模式感兴趣。
数据库是化学生产过程的历史数据。我认为我应该逐列应用某种模式识别方法,因为每一列代表一个过程变量,并且该值来自一个变送器。
我的目标是预测缺失数据是由于机械故障还是注册过程中的偏差或其他原因。然后,如果需要,我应该应用某种填充方法。
您有什么建议吗?提前感谢!
我将反过来思考这个问题,对缺失数据序列进行建模,并将所有您拥有的数据标记为特殊值“0”,而缺失的实例标记为“1”。
一个很棒的问题!
告诉我进展如何。
你帮助我保持了理智。谢谢!!
我很高兴听到这个,Patricia!
如何知道是应用平均值还是用众数替换?
尝试两者,看看哪种能产生更熟练的模型。
你好 Sachin,
众数受异常值影响,而平均值受异常值影响较小。
如果我错了,请纠正我 @Jason
我想您是指“中位数”不受异常值影响。“众数”只是最常见的值。
如果我有一个11x11的表格,其中有20个缺失值,是否有方法可以创建一个列表来识别这些值?
假设第一列是名字,第一行是第1天到第10天。有些名字没有在所有日子里出现,因此存在缺失的间隔。我将此表放入代码中,而不是读取表格,而是得到一个列表,其中包含:
Name, day 2, day 5, day 7
Name, Day 1, day 6
我明白这可能需要一些时间来回答,但如果您能告诉我这是可能的,甚至可能知道从哪里开始这个项目,那将非常有帮助!
当然,如果缺失值用nan或类似值标记,您可以使用Pandas检索带有缺失值的行。
我们可以自己编写算法来填充缺失值吗??
如果可能,我该如何实现?
是的。
您可以编写一些if语句,并在Pandas DataFrame中填入n/a值。
我也会建议使用统计或模型,并比较结果。
嗨,Jason,
我正在尝试为泰坦尼克号数据集准备数据。其中一个列是CABIN,它具有像‘A22’,‘B56’等值。该列包含最多的缺失值。起初我考虑删除此列,但我认为这对于预测幸存者可能是一个重要的变量。
我正在尝试找到一种填充这些空值的方法。是否有方法可以填充字母数字为空值?
如果不存在自动方法,我正在考虑根据姓名、兄弟姐妹数量、父母子女数量和班级列来填充这些记录。例如,对于缺失值,尝试查看是否有任何亲属并使用他们的客舱号来替换缺失值。
AGE列也是缺失值。有什么想法?
听起来像是一个分类变量。您可以将其编码为整数。您也可以为缺失值分配一个“未知”整数值(例如-999)。
也许您可以开发一个模型来预测客舱号码,看看它是否有效。
下午好,我运行了这段代码 pd.read_csv(r’C:\Users\Public\Documents\SP_dow_Hist_stock.csv’,sep=’,’).pct_change(252)
它给了我股票收益的缺失值(NAN)。我该如何解决?
pd.read_csv(r’C:\Users\Public\Documents\SP_dow_Hist_stock.csv’,sep=’,’)
Out[5]
Unnamed: 0 S&P500 Dow Jones
0 Date close Close
1 1-Jan-17 2,275.12 24719.22
2 1-Jan-16 1,918.60 19762.60
3 1-Jan-15 2,028.18 17425.03
4 1-Jan-14 1,822.36 17823.07
5 1-Jan-13 1,480.40 16576.66
6 1-Jan-12 1,300.58 13104.14
7 1-Jan-11 1,282.62 12217.56
8 1-Jan-10 1,123.58 11577.51
9 1-Jan-09 865.58 10428.05
10 1-Jan-08 1,378.76 8776.39
11 1-Jan-07 1,424.16 13264.82
12 1-Jan-06 1,278.73 12463.15
13 1-Jan-05 1,181.41 10717.50
14 1-Jan-04 1,132.52 10783.01
15 1-Jan-03 895.84 10453.92
16 1-Jan-02 1,140.21 8341.63
17 1-Jan-01 1,335.63 10021.57
18 1-Jan-00 1,425.59 10787.99
19 1-Jan-99 1,248.77 11497.12
20 1-Jan-98 963.36 9181.43
21 1-Jan-97 766.22 7908.25
22 1-Jan-96 614.42 6448.27
23 1-Jan-95 465.25 5117.12
24 1-Jan-94 472.99 3834.44
25 1-Jan-93 435.23 3754.09
26 1-Jan-92 416.08 3301.11
27 1-Jan-91 325.49 3168.83
28 1-Jan-90 339.97 2633.66
29 1-Jan-89 285.4 2753.20
.. … … …
68 1-Jan-50 16.88 235.42
69 1-Jan-49 15.36 200.52
70 1-Jan-48 14.83 177.30
71 1-Jan-47 15.21 181.16
72 1-Jan-46 18.02 177.20
73 1-Jan-45 13.49 192.91
74 1-Jan-44 11.85 151.93
75 1-Jan-43 10.09 135.89
76 1-Jan-42 8.93 119.40
77 1-Jan-41 10.55 110.96
78 1-Jan-40 12.3 131.13
79 1-Jan-39 12.5 149.99
80 1-Jan-38 11.31 154.36
81 1-Jan-37 17.59 120.85
82 1-Jan-36 13.76 179.90
83 1-Jan-35 9.26 144.13
84 1-Jan-34 10.54 104.04
85 1-Jan-33 7.09 98.67
86 1-Jan-32 8.3 60.26
87 1-Jan-31 15.98 77.90
88 1-Jan-30 21.71 164.58
89 1-Jan-29 24.86 248.48
90 1-Jan-28 17.53 300.00
91 1-Jan-27 13.4 200.70
92 1-Jan-26 12.65 157.20
93 1-Jan-25 10.58 156.66
94 1-Jan-24 8.83 120.51
95 1-Jan-23 8.9 95.52
96 1-Jan-22 7.3 98.17
97 1-Jan-21 7.11 80.80
[98 行 x 3 列]
pd.read_csv(r’C:\Users\Public\Documents\SP_dow_Hist_stock.csv’,sep=’,’).pct_change(251)
Out[7]
Unnamed: 0 S&P500 Dow Jones
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 NaN NaN NaN
8 NaN NaN NaN
9 NaN NaN NaN
10 NaN NaN NaN
11 NaN NaN NaN
12 NaN NaN NaN
13 NaN NaN NaN
14 NaN NaN NaN
15 NaN NaN NaN
16 NaN NaN NaN
17 NaN NaN NaN
18 NaN NaN NaN
19 NaN NaN NaN
20 NaN NaN NaN
21 NaN NaN NaN
22 NaN NaN NaN
23 NaN NaN NaN
24 NaN NaN NaN
25 NaN NaN NaN
26 NaN NaN NaN
27 NaN NaN NaN
28 NaN NaN NaN
29 NaN NaN NaN
.. … … …
68 NaN NaN NaN
69 NaN NaN NaN
70 NaN NaN NaN
71 NaN NaN NaN
72 NaN NaN NaN
73 NaN NaN NaN
74 NaN NaN NaN
75 NaN NaN NaN
76 NaN NaN NaN
77 NaN NaN NaN
78 NaN NaN NaN
79 NaN NaN NaN
80 NaN NaN NaN
81 NaN NaN NaN
82 NaN NaN NaN
83 NaN NaN NaN
84 NaN NaN NaN
85 NaN NaN NaN
86 NaN NaN NaN
87 NaN NaN NaN
88 NaN NaN NaN
89 NaN NaN NaN
90 NaN NaN NaN
91 NaN NaN NaN
92 NaN NaN NaN
93 NaN NaN NaN
94 NaN NaN NaN
95 NaN NaN NaN
96 NaN NaN NaN
97 NaN NaN NaN
[98 行 x 3 列]
也许将你的代码和问题发布到stackoverflow?
嗨,Jason,
感谢您宝贵的写作。
我有一个问题:
我们也可以使用Pandas fillna()函数替换NaN值。在我看来,这比Imputer类更通用,因为在一个语句中,我们可以对不同的列采用不同的策略。
df.fillna({‘A’:df[‘A’].mean(),’B’:0,’C’:df[‘C’].min(),’D’:3})
您怎么看?两者之间是否存在性能差异?
好建议。
我不知道性能差异。
在任何纠正措施(如填充)可以采取时,是否有推荐的NaN值与有效值的比例?
如果我们有一列大部分值都为空,那么完全忽略该列作为特征会更好吗?
没有,这取决于具体问题。也许可以做一些实验,看看模型对缺失值的敏感程度。
嗨,Jason,
感谢您的帖子,我想问一下,如何填充一列中缺失的文本值,该列包含文本标签或空白。
好问题,我暂时不确定。也许可以从简单的缺失值掩码开始。
填充分类列的nan
df = df.fillna(df[‘column’].value_counts().index[0])
这将用最常见的分类值填充所有列中的缺失值。
非常感谢Jason!但我有一个小问题,如果我们想用每行的平均值而不是列的平均值来替换缺失值,该怎么办?该怎么做?如果您有任何线索,请告诉我。再次感谢Jason。
你为什么要这样做?
numpy.mean()允许您指定计算平均值的轴。它会为您完成。
嗨,Jason,
我想问您如何处理缺失的时间戳(日期-时间值),它们是分类问题中的一组预测变量。您会标记它们并将其标记为缺失,还是将其填充为其余时间戳的众数?
这里有一些想法
https://machinelearning.org.cn/handle-missing-timesteps-sequence-prediction-problems-python/
嗨,Jason,
我是您的忠实粉丝。
我有一个关于填充缺失数值的问题。我真的不想删除它们,我想将它们填充为一个类似于NaN但类型为数值的值?将它编码为-1是否可行?(0已经被使用了)。
我想我是在实现将NaN分类变量分类为未知,并创建另一个特征列来指示它缺失。
谢谢,
NaN是数值类型。它是一个有效的浮点数。
您可以使用-999或您喜欢的任何值。
请注意,您的模型是否支持它们,或者在建模之前对值进行归一化。
你好 Jason,
您在这里提到:“如果您选择使用列的平均值进行填充,那么这些列的平均值将需要存储到文件中,以供将来对具有缺失值的新数据使用。”,但我想问:
在创建训练集和测试集(使用数据集的平均值)之前填充数据是否会导致数据泄露?在机器学习项目的数据管道中处理缺失数据的最佳方法是什么?
假设我通过填充平均值来填充。对于模型调优,我是否使用训练集的平均值来填充测试集?
是的。您需要计算用于填充的值,然后将其应用于测试集。
sklearn库有一个您可以用于管道的填充器。
https://scikit-learn.cn/stable/modules/generated/sklearn.preprocessing.Imputer.html
嗨,Jason,
再次感谢这篇非常好的文章!
有没有一个巧妙的方法可以清除某一列中包含文本(即字符串)的所有行,例如List.ImportantColumn。
这破坏了我的绘图,出现了“无法将字符串转换为浮点数”。
提前感谢!
是的,您可以使用简单的NumPy数组索引删除或替换这些值。
例如,如果您有‘?’,您可以这样做:
嗨,Jason,
我尝试使用dropna删除数据集中包含缺失值的整行,然后isnull().sum()在数据集中也显示零缺失值。但是当我运行算法时,我收到一个错误。
Error : Input contains NaN, infinity or a value too large for dtype(‘float64’)
这清楚地表明仍然存在一些缺失值。
我该如何处理这个问题,提前感谢。
也许可以打印准备好的数据内容,以确认NaN值确实已被移除?
嗨,Jason,
感谢这篇帖子,我正在使用CNN进行回归,并在数据归一化后在训练样本中发现了一些NaN值。如何在归一化数据后使用imputer填充缺失值?
上面的教程没有帮助吗?
我应该将Imputer函数应用于训练集和测试集吗?
是的,但是如果imputer需要学习/估计,它应该从训练数据中学习/估计,并应用于训练集和测试集,以避免数据泄露。
我感觉Imputer移除了Nan值,而不是替换它们。例如,我的特征向量长度是14,应用Imputer函数后有2个NaN值,向量长度是12。这意味着2个NaN值被移除了。但我使用了以下设置
imputer = Imputer(missing_values=np.nan, strategy=’mean’, axis=0)
我不知道你那里发生了什么,也许可以发到Stack Overflow上搜索一下?
你的意思是,我应该在训练数据上拟合它,然后像这样应用于训练集和测试集
imputer = Imputer(strategy=”mean”, axis=0)
imputer.fit(X_train)
X_train = imputer.transform(X_train)
X_test = imputer.transform(X_test)
看起来不错。
感谢这篇帖子!!!
一个拥有超过4000行的数据集,可以按第一列进行分组,假设有许多列(例如20列)和少量列(例如14列)包含NaN(缺失值)。
如何通过迭代方法(使用groupby,transform和apply)用相应列的平均值填充NaN?
抱歉,我不明白。也许你可以详细说明你的问题?
实际上,我想填充每列中的缺失值。值是相应列的平均值。有什么迭代方法吗?
你说的迭代方法是什么意思?
是迭代imputer吗?其中缺失值充当因变量,自变量是其他特征
不行。
替换零之后,我可以将其保存为新的数据集吗?
是的,调用dataframe的to_csv()。
这是什么意思?
这是一个函数,可以在这里了解更多信息
https://pandas.ac.cn/pandas-docs/stable/reference/api/pandas.DataFrame.to_csv.html
import numpy as np
import pandas as pd
mydata = pd.read_csv(‘diabetes.csv’,header=None)
mydata.head(20)
0 1 2 3 4 5 6 7 8
0 Pregnancies Glucose BloodPressure SkinThickness Insulin BMI DiabetesPedigreeFunction Age Outcome
1 6 148 72 35 0 33.6 0.627 50 1
2 1 85 66 29 0 26.6 0.351 31 0
3 8 183 64 0 0 23.3 0.672 32 1
4 1 89 66 23 94 28.1 0.167 21 0
5 0 137 40 35 168 43.1 2.288 33 1
print((mydata[0] == 0).sum()) — 对于任何列,它总是显示0
0 >>>>>>> ....这里有什么不对吗?
而我的数据集中有0
0 Pregnancies
1 6
2 1
3 8
4 1
5 0>>>>>>>>>
6 5
7 3
8 10
9 2
10 8
11 4
12 10
13 10
14 1
15 5
16 7
17 0 >>>>>>
也许将你的代码和问题发布到stackoverflow?
你好,
一年多以后,我遇到了和你一样的问题。当我搜索0时,它不起作用。但是,当我搜索“0”时,它起作用了,这意味着表是用字符串填充的,而不是数字……有什么办法处理吗?
此致
也许你的数据被加载为字符串了?
尝试将其转换为数字
你好,先生,
对于我的数据,在执行了以下说明后,我仍然遇到相同的错误
dataset= dataset.replace(0, np.NaN)
dataset.dropna(inplace=True)
dataset= dataset.replace(0, np.Inf)
dataset.dropna(inplace=True)
print(dataset.describe())
F1 F2 F3 F4
count 1200.000000 1200.000000 1200.000000 1200.000000
mean 0.653527 0.649447 1.751579 inf
std 0.196748 0.194933 0.279228 NaN
min 0.179076 0.179076 0.731698 0.499815
25% 0.507860 0.506533 1.573212 1.694007
50% 0.652066 0.630657 1.763520 1.925291
75% 0.787908 0.762665 1.934603 2.216663
max 1.339335 1.371362 2.650390 inf
我该如何摆脱这个问题?
很遗憾听到这个消息,也许可以尝试将你的代码和问题发布到Stack Overflow上?
df.replace(-np.Inf, 0 )
df.replace(np.Inf, 0 )
如何在python中进行分类数据插补?
您可以使用整数编码(标签编码)、独热编码甚至词嵌入。
嗨 Jason
我是Python新手,我正在学习您给出的例子。出于某种原因,当我运行代码来计算零值时,代码返回的结果表明任何列中都没有零值。
您能帮我一下吗?
很抱歉听到这个消息,我在这里有一些建议。
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,Jason,
很棒的帖子。非常感谢。
假设我有一个没有标题的数据集,无法识别列,我该如何处理不一致的数据,例如,年龄有值2500,但不知道这一列是关于年龄的,有什么想法吗?
您可以使用统计数据来识别异常值。
https://machinelearning.org.cn/how-to-use-statistics-to-identify-outliers-in-data/
嗨,Jason,
很好的文章。如何(在python中)添加一个额外的特征,指示缺失值为1,不缺失为0?这是一个合理的解决方案吗?
谢谢你。
很好的问题。
您可以遍历所有行,并在另一个数组中标记0和1值,然后将其与原始特征/行进行堆叠。
Pima Indians Diabetes Dataset已不存在了🙁
谢谢,我已经更新了链接。
AutoML领域的当前情况如何?研究人员实际上想带来什么?
好问题,我需要更多地了解那个领域。
等到以后您了解了,请告诉我。
谢谢您的回复!!
[忽略之前错放的帖子]
Jason,
非常感谢您准备这些很棒的教程!
为了用平均列值填充缺失值,我不得不从
from sklearn.preprocessing import Imputer
…
# 使用列的平均值填充缺失值
imputer = Imputer()
到
切换到
…
from sklearn.impute import SimpleImputer
感谢分享。
German Niebles 2020年1月5日上午4:00 #
此致
不客气。
Raj 2020年1月30日下午6:12 #
看这里
https://machinelearning.org.cn/handle-missing-timesteps-sequence-prediction-problems-python/
谢谢 Jason!
不客气。
Shreya 2020年2月29日上午3:37 #
我大约有40万条数据。
我的数据集的形状是(400000,114)。
我想先插补数据,然后应用特征选择,例如RFE,以便我可以用重要的特征来训练我的模型,而不是所有114个特征。
values = dataset.values
但是,在使用SimpleImputer和MinMax scaler进行数据归一化时,我无法理解如何
imputer = SimpleImputer()
scaler = MinMaxScaler(feature_range=(0, 1))
imputedData = imputer.fit_transform(values)
normalizedData = scaler.fit_transform(imputedData)
如何使用这些归一化后的数据??
因为在正常数据集中,我后面将X,Y标签设为
X = dataset.drop([‘target’], axis=1)
y = dataset.target
这里后面如何使用RFE?
Shreya 2020年2月29日上午3:41 #
Jason Brownlee 2020年2月29日上午7:20 #
Shreya 2020年2月29日下午3:07 #
我已经用少量数据测试过了,效果很好。
但有一个要求,我必须使用这么大的数据量,即40万条数据,114个特征。
另外,RandomForest上的RFE运行非常耗时。
如果我使用model = LogisticRegression(‘saga’),那么时间会少一些,但我遇到了警告,我无法解决,因为
ConvergenceWarning: The max_iter was reached which means the coef_ did not converge
“coef_ did not converge”,ConvergenceWarning)
对于这个大型数据集,我应该如何进行特征选择?
Jason Brownlee 2020年3月1日上午5:22 #
Jason Brownlee 2020年2月29日上午7:20 #
manjunath 2020年2月29日上午6:00 #
请看这个教程
https://machinelearning.org.cn/handle-missing-timesteps-sequence-prediction-problems-python/
你好,Jason
Bruno Campetella 2020年4月4日上午2:05 #
谢谢
如果我们插补了数据集中的某个列,数据分布将会改变,并且改变将取决于插补策略。这反过来会影响不同的ML算法的性能。我们调整预测不是为了原始问题,而是为了“新”数据集,它很可能与真实数据集不同。我的问题是,为了避免错误预测或过高估计我们算法的性能,我们是否应该避免在测试数据集中有任何NA插补值?我想我们可以在训练数据中使用它们,并使用不同的插补技术来检查测试数据(没有插补NA)上算法的性能。
Jason Brownlee 2020年4月4日上午6:25 #
是的。好问题!
嗨,Jason,
Deeksha Mahapatra 2020年5月11日上午3:42 #
首先,非常感谢你的教程!这是我机器学习的首选之地。
我正在尝试有条件地插补我的数据集中的值。假设我有三列,如果第一列是1,那么第二列是0,第三列是0;如果第一列是2,那么第二列是Mean(),第三列是Mean()。我尝试运行一个if语句和any()函数,并单独定义了条件。但是,条件并没有根据条件得到满足,我得到的是所有平均值或所有零值。
非常感谢!
谢谢!
Jason Brownlee 2020年5月11日上午6:08 #
Deeksha Mahapatra 2020年5月11日下午4:43 #
太棒了!
感谢这篇帖子。
Parthiv 2020年6月14日上午8:27 #
如果我错了,请纠正我。
将这些技术应用于训练数据对我有用。但是,如果实时数据(测试数据)以标准间隔(100毫秒)接收,那么诸如LGBM、XGBoost和Catboost(scikit)之类的算法具有内在的功能,可以被使用。
Jason Brownlee 2020年6月15日上午5:58 #
谢谢您的回复。
Parthiv 2020年6月19日上午6:58 #
只是一个澄清。如果多个传感器的一个实例数据到达,并且每100毫秒就有一些缺失值,是否可以仅基于当前实例进行分类。(一次一个实例)。
我的假设是,我们需要多个实例来计算统计数据,即使是流数据。
Jason Brownlee 2020年6月19日下午1:10 #
一般来说,您可以根据您的需求来构建预测问题,例如,基于您拥有的数据和预测时需要的数据。
Parthiv 2020年6月19日下午3:27 #
Jason Brownlee 2020年6月20日上午6:06 #
尊敬的Jason博士,
Anthony The Koala 2020年7月5日下午10:31 #
背景信息和问题
背景信息
我没有使用“马匹结肠”数据进行缺失值处理,而是构建了一个小型版本的鸢尾花数据集。我必须打乱数据,以获得物种0、1或2的均匀分布。否则,如果我取前20行,最后一列将全是物种0。因此,我打乱了数据。
我的iris20数据看起来是这样的——前四列的顺序与原始鸢尾花数据相同,最后一列是各种物种。
我从我的iris20数据中“随机”移除了10个值,称之为iris20missing
问题
我已成功预测了鸢尾花的物种类型,无论是物种0、1还是2。
示例
我的问题:在列表8.19,第3倒数第1行,第84页(第101页,共398页)
row被包含在括号[]中。
也就是说,我们有,例如,row = [[6.3 ,NaN,4.4 ,1.3]]
请问为什么要在predict函数中双重包含数组?
当我这样做时
我得到错误。
感谢您的时间,
悉尼的Anthony
为什么要把row包含为[row],因为row已经被括号包含了。
这就是为什么是.predict([row])而不是.predict(row)
干得好!
predict()函数需要一个2D矩阵输入,一行数据表示为Python中的矩阵是[[a,b,c]]。
首先,
提前感谢您的回复。我很感激。
请允许我问一个关于您答案的问题。
背景信息
在上面的例子中,我们必须将变量‘row’构建为一个2D矩阵才能在predict()函数中使用。这里‘row’从一个大小为4的数组改变为一个1x4的矩阵。
我了解到,您可以构建一个n x m矩阵,并让模型预测一个n x m矩阵
举个例子
回想一下,在我上面的例子中,我创建了一系列行,并对这些行上的模型进行了单独预测
现在,如果我们创建一个n x m矩阵并将该n x m矩阵输入到predict()函数中,我们应该期望与单个预测相同的结果。
结果与进行单独预测的结果相同。因此,我明白了predict()函数期望一个矩阵,并且如果预测单行,则将单行制成1xm矩阵。
结论:predict()函数期望一个矩阵,我们可以创建一个包含我们要预测的行的n x m矩阵,并获得多个结果。
再次提前感谢
悉尼的Anthony
是的。
也许这能帮助你澄清
https://machinelearning.org.cn/make-predictions-scikit-learn/
尊敬的Jason博士,
感谢您在https://machinelearning.org.cn/make-predictions-scikit-learn/ 发布的博客。
与回答我关于预测的问题相关的是“类预测”、“单个类预测”和“多个类预测”部分。(这些部分按1、3和2的顺序呈现)。
变量Xnew的结构是[[],[]],这是一个2D结构。这是为了进行一次预测。
在多个类预测中,Xnew是一个2D矩阵。在示例中,它是一个3x2的2D矩阵
在单类预测和多类预测这两种情况下,我们都以以下形式输入2D矩阵
总之,预测需要我们的特征矩阵是2D的,无论是1 x m还是n x m,其中1或n是预测的数量,m是特征的数量。
谢谢你,
悉尼的Anthony
尊敬的Jason博士,
我想分享我删除数据集中特定行的两种方法,根据子标题4,“删除具有缺失值的行”。
如何从特定列中删除特定值——两种方法
方法1,根据标题4=您书中的第73页(第398页的第90页)的列表7.16。
方法2——使用数组
最后一个方法是为您的数据集不是DataFrame的情况准备的。
谢谢你,
悉尼的Anthony
感谢分享!
嗨,Jason,
我只是想知道,数据插补(例如,用相应列的算术平均值替换所有缺失值)是否真的会导致数据泄露,从而在训练过程中引入模型偏差?毕竟,这样的数据插补会用模型在训练时应该看不见的数据实例(行)提供的信息来填充数据集。
如果这确实是一个问题,您有什么建议?是否应该将数据插补添加到管道中,从而为交叉验证的每个折叠单独实现它,以及其他特征选择、预处理和特征工程步骤?
非常感谢,
Levente
只要您只使用训练数据来计算统计数据,就不会。
我该如何对“Age”变量进行类似案例的平均值插补,该变量有缺失值?
平均值计算为值之和除以值的总数。
本教程将帮助您入门。
https://machinelearning.org.cn/statistical-imputation-for-missing-values-in-machine-learning/
[‘toy stori’,
‘grumpier old men’,
‘heat’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
‘nan’,
#################
嗨Jason,我应用了嵌入技术。如何处理nan值?我将改进我的结果。
如果您在数据中有nan值,可以尝试删除它们、插补它们、屏蔽它们等。
如果您的模型中有nan值,那么您的模型就会损坏,可能是在训练过程中出现梯度爆炸或梯度消失。
精确率 召回率 f1分数 支持数
class0(0.5) 0.00 0.00 0.00 0
class1(1) 0.00 0.00 0.00 8
class2(1.5) 0.00 0.00 0.00 2
class3(2) 0.00 0.00 0.00 10
class4(2.5) 0.02 0.22 0.03 9
class5(3) 0.00 0.00 0.00 75
class6(3.5) 0.00 0.00 0.00 16
class7(4) 0.00 0.00 0.00 74
class8(4.5) 0.00 0.00 0.00 17
class9(5) 0.00 0.00 0.00 35
accuracy 0.01 246
macro avg 0.00 0.02 0.00 246
weighted avg 0.00 0.01 0.00 246
[[ 0 0 0 0 0 0 0 0 0 0]
[ 1 0 0 0 7 0 0 0 0 0]
[ 1 0 0 0 0 0 1 0 0 0]
[ 1 2 0 0 5 0 2 0 0 0]
[ 5 2 0 0 2 0 0 0 0 0]
[ 7 21 0 0 40 0 7 0 0 0]
[ 2 7 0 0 7 0 0 0 0 0]
[13 32 0 0 28 0 1 0 0 0]
[ 1 8 0 0 7 0 1 0 0 0]
[ 1 21 0 0 12 0 1 0 0 0]]
好的,我移除了“nan”值。这是我的新结果。我期待一个积极的回应。
抱歉,你到底遇到了什么问题?也许你可以重新表述或详细说明你的问题?
RangeIndex: 100836 entries, 0 to 100835
Data columns (total 6 columns)
# Column Non-Null Count Dtype
— —— ————– —–
0 userId 100836 non-null int64
1 movieId 100836 non-null int64
2 timestamp 100836 non-null int64
3 title 745 non-null object
4 genres 745 non-null object
5 rating 100836 non-null float64
dtypes: float64(1), int64(3), object(2)
memory usage: 4.6+ MB
#################################
嗨,Jason,
我删除了“title, genre”中的所有缺失值,但我的总样本观测值为745。为什么没有改进?“title, genre”列是文本数据。如何为文本数据生成缺失值?
也许你可以使用最常见的词或短语?
也许你可以使用特殊的“无文本”短语?
嗨 Jason
感谢您提供有用的教程!
我的数据集中有一个“传感器饱和问题”:被截断的测量值在零和较低测量限(A)之间,或者在上限(B)之上。
我是否可以应用Scikit-learn的IterativeImputer方法根据AB来插补这些值?我基本上想将极端值(尾部)添加到我的正态分布曲线中。
附加信息
使用Python 3.9.5,新手用户。
我查阅了PyMC3包(https://docs.pymc.io/notebooks/censored_data.html)。
但是这个例子中使用的包工作得不太好(https://discourse.pymc.io/t/attributeerror-module-arviz-has-no-attribute-geweke/6818)
也许可以尝试一下。
你好 Jason,
如果我有一整行NaN,通常怎么处理?我应该直接从我的数据集中删除它吗?
您有什么可以参考的关于这类问题的资料吗?我的数据集有42k行,我看到其中一些是完全空的。
提前感谢,
Murilo
如果得到一整行NaN,请删除它。如果您只有少量字段是NaN,可以尝试插补。