这篇文章是作为 数据科学博客马拉松
概述
数据为我们提供了分析和预测未来事件的能力。 每天,越来越多的公司正在采用数据科学技术,如预测性预测、聚类等。 虽然不断学习复杂的 ML 和 DL 算法非常有趣,但不应忘记掌握基本知识 数据预处理. 数据预处理的重要部分之一是处理缺失值。 这是关于如何处理不同类型的缺失数据的完整指南。
内容
- 为什么处理缺失值很重要?
- 缺失值背后的原因
- 缺失值的类型
- 检查数据集中的缺失值
- 可视化缺失值
- 删除缺失值的行
- 删除缺失值的列
- 连续变量的插补
- 均值插补
- 中位数插补
- 用回归预测缺失值
- 分类数据中的缺失值
- 时间序列数据中的缺失值
- 前向填充缺失值
- 向后填充缺失值
- 线性插值
- 对缺失值鲁棒的算法
- 结论
为什么处理缺失数据很重要?
现实世界中的数据在大多数情况下都有很多缺失的数据。 每个值丢失的原因可能不同。 可能有数据丢失或损坏,或者也可能有特定原因。 缺失的数据会降低模型的预测能力。 如果你应用缺失数据的算法,那么参数估计就会出现偏差。 如果您不处理丢失的数据,您就无法对结果充满信心。
缺失值背后的原因
有没有想过数据集中丢失数据背后的原因?
数据丢失背后的一些可能原因是:
- 人们不会在数据收集调查中提供有关某些问题的信息。 例如,有些人可能不愿意分享有关他们的工资、饮酒和吸烟习惯的信息。 这些是人们故意遗漏的
- 在某些情况下,数据是从各种可用的过去记录中积累的,而不是直接积累的。 在这种情况下,数据损坏是一个主要问题。 由于维护率低,部分数据损坏导致数据丢失
- 数据收集过程中的不准确也会导致数据丢失。 例如,在手动数据录入中,很难完全避免人为错误
- 设备不一致导致测量错误,进而无法使用。
缺失值的类型
数据丢失的原因多种多样。 我们可以将它们分为三个主要组:完全随机丢失、随机丢失、不随机丢失。
1. 完全随机缺失 (MCAR)
缺失的数据不遵循任何特定模式,它们只是随机的。 这些数据的缺失与其余变量无关或独立。 不可能用其余的可变数据来预测这些值。 例如,在数据收集过程中,由于粗心大意丢失了特定样本。 这是一个理想的情况,统计分析不会有偏差。 但是除非非常确定,否则您不应该假设 MCAR 的存在,因为这是一种罕见的情况。
2. 随机缺失 (MAR)
与 MCAR 不同的是,这里的数据在特定子集中丢失。 可以借助其他功能来预测数据是否存在/不存在。 但是,您无法自己预测丢失的数据。
例如,让我们考虑一项关于在互联网上花费的时间的调查,其中有一个部分是关于在 Netflix、亚马逊 Prime 等平台上花费的时间。 据观察,老年人(45 岁以上)比年轻人更不可能填满它。 这是 MAR 的一个例子。 在这里,“年龄”参数决定数据是否会丢失。 MAR 比 MCAR 更常见。
3. 不随机丢失 (NMAR)
这是一个严重而棘手的情况。 假设调查的目的是衡量对社交媒体的过度使用/上瘾。 如果过度使用社交媒体的人没有故意填写调查,那么我们就有了 NMAR 的案例。 这很可能会导致结果的偏差。 通常的方法,如删除行/列,插补将不起作用。 为了解决这个问题,需要对该领域有深入的了解。
现在我们已经看到了不同类型的缺失数据,让我们继续讨论处理它们的各种方法。
检查缺失值
当您有数据集时,第一步是检查哪些列缺少数据以及有多少。 让我们用数据科学中最著名的数据集来学习,当然是泰坦尼克号幸存者! 使用 pandas read_csv 函数读取数据集,如下所示。
train=pd.read_csv('../input/titanic/train.csv') test=pd.read_csv('../input/titanic/test.csv') print('训练数据形状:', train.shape ) print('测试数据形状:', test.shape) train.head()
来源:来自作者 Kaggle 笔记本的图片
现在我们有了泰坦尼克号数据的训练和测试数据框。
如何检查哪些列缺少数据,有多少?
“isnull()”函数用于此目的。 当您与 isnull 一起调用 sum 函数时,每列中缺失数据的总和就是输出。
missing_values=train.isnull().sum() 打印(missing_values)
乘客 ID 0 幸存 0 Pclass 0 姓名 0 性别 0 年龄 177 SibSp 0 Parch 0 票 0 票价 0 客舱 687 登船 2 dtype:int64
请注意,有 3 列缺少值:Age、Cabin、Embarked
尽管我们知道每列中缺失了多少个值,但必须知道它们占总数的百分比。 所以,让我们用一行代码来计算。
mis_value_percent = 100 * train.isnull().sum() / len(train) 打印(mis_value_percent)
PassengerId 0.000000 0.000000幸存0.000000 Pclass名称0.000000 0.000000性别年龄19.865320 SibSp 0.000000 0.000000烘干票务0.000000 0.000000票价客舱77.104377走上0.224467 D型:float64
很明显,77% 的“Cabin”列丢失了,这是一个非常重要的百分比。 Age 有大约 19% 的数据缺失,而 Embarked 仅缺失 0.2%。 这就是我们对缺失数据的定量分析。 定性呢? 继续阅读!
使用 Missingno 可视化缺失值
你猜怎么着? 我们有一个 python 包,专门用于可视化和探索数据集的缺失数据。 “Missingno”python 包。 继续并快速安装它
点安装缺失没有
使用它,我们可以以热图、条形图和矩阵的形式进行可视化。 通过分析它们的分布方式,您可以得出它们属于 MCAR、MAR 或 NMAR 的类别。 我们还可以找到包含缺失的列与目标列的相关性
首先使用missingno 库的'bar()' 函数为非空值制作条形图。 您已将 pandas 数据框传递给此函数。
导入 missingno 作为 msno msno.bar(train)
来源:来自作者 Kaggle 笔记本的图片
接下来,我们可以绘制矩阵可视化。 这有助于我们了解缺失的数据是如何通过数据分布的,即它们是局部的还是均匀分布的,或者是否存在任何模式和许多此类问题。
msno.matrix(火车)
在矩阵图中,您将看到每个缺失数据的空行。 请注意,“Embarked”列只有两个随机缺失的数据,它们不遵循任何模式。 它们可能在数据采集过程中丢失了。 因此,这可以归类为完全随机丢失。
age 和 Cabin 列可能是 MAR。 但我们要确保它们之间没有相关性。
怎么做?
幸运的是,missingno 包还提供了“热图”功能。 使用它我们可以发现不同列的缺失数据之间是否存在任何相关性。
msno.heatmap(火车)
显示输出!
热图显示 Age 和 Cabin 列的缺失数据之间没有如此强的相关性。 因此,这些列的缺失数据可以归类为 MAR 或随机缺失。
我希望您清楚如何分析缺失值。 接下来,我将继续讨论处理这些缺失数据的不同方法。
删除缺失值的行
这是一种简单的方法,我们删除所有具有属于特定列的缺失值的行。 尽管这很容易,但它有一个巨大的缺点。 您最终可能会丢失大量数据。 这将减少数据集的大小并使您的模型预测有偏差。 只有当缺失值的数量非常少时,才应该使用它。
例如,“Embarked”列只有 2 个缺失值。 因此,我们可以删除缺少此列的行。 按照下面的代码片段。
print('Dataset before :', len(train)) train.dropna(subset=['Embarked'],how='any',inplace=True) print('Dataset after :', len(train)) print( '缺失值:',train['Embarked'].isnull().sum())
之前的数据集:891 之后的数据集:889 缺失值:0
想象一下,如果您对“年龄”列执行相同操作。 您将丢失大约 77% 的数据!
删除列
当一列有大量缺失值时,用我们拥有的最少可用的真实数据来估算这些值是没有意义的。 因此,当任何列的缺失值超过 80% 时,您只需从分析中删除该列即可。 在我们的例子中,“Cabin”缺少 77% 的数据,因此您可以选择删除此列。
确保删除的列对您的分析不重要。 如果是这样,您应该尝试获取更多数据,然后估算缺失值。
连续变量的插补
火车['年龄'][:10]
0 22.0 1 38.0 2 26.0 3 35.0 4 35.0 5 NaN 6 54.0 7 2.0 8 27.0 9 14.0 姓名:年龄,数据类型:float64
train['Age']=train['Age'].replace(np.NaN,train['Age'].mean()) train['Age'][:10]
0 22.000000 1 38.000000 2 26.000000 3 35.000000 4 35.000000 5 29.699118 6 54.000000 7 2.000000 8 27.000000 9 14.000000 64 XNUMX XNUMX XNUMX XNUMX XNUMX
您可以看到“NaN”已替换为 29.699(计算平均值)。
均值插补有一定的缺点。 如果数据分布很不均匀,有很多异常值,那么均值就不能反映数据的实际分布。 均值受极值或异常值的影响很大。 因此,如果数据没有很多异常值并且遵循接近正态分布,请使用均值插补
中位数插补
连续特征的缺失值可以用剩余非空值的中值填充。 与均值不同,中位数的优点是不受异常值的影响。 让我们在这里实现它。
train['Age']=train['Age'].replace(np.NaN,train['Age'].median()) train['Age'][:10]
您可以观察到中值 (28.0) 已被填充以代替 NaN 值。
同样,您也可以执行模式插补。 通常,使用该模式进行插补对于分类缺失值很流行。 我将在后面的部分深入介绍
用回归预测缺失值
如果我们可以在其他变量的帮助下预测它们,而不是在所有地方填充单个平均值或中值,该怎么办?
是的! 我们可以使用具有非空值的特征来预测缺失值。 可以建立回归或分类模型来预测缺失值。 让我们为泰坦尼克号数据集的“年龄”列实现这一点。
我们可以处理用于构建模型的数据。 “年龄”特征将是目标变量。
x_train: 具有“年龄”值的数据集行将被过滤。 “年龄”是目标 x_测试: 它是具有非空值的“年龄”列
火车 将有缺失年龄值的数据,这将被预测(y_pred)
将熊猫导入为 pd data=pd.read_csv('../input/titanic/train.csv') data = data[["Survived", "Pclass", "Sex", "SibSp", "Parch", "Fare ", "Age"]] 数据["Sex"] = [1 if x=="male" else 0 for x in data["Sex"]] test_data = data[data["Age"].isnull()] data.dropna(inplace=True) x_train = data.drop("Age", axis=1) x_test = test_data.drop("Age", axis=1) y_train = data["Age"]
让我们为这些数据拟合一个线性回归模型。 我将在这里使用 sklearn 库。
从 sklearn.linear_model 导入 LinearRegression 模型 = LinearRegression() model.fit(X_train, y_train) y_pred = model.predict(X_test)
现在,我们在 y_pred 中预测了 Age 列的空值。
我将打印出几个测试输入和预测输出的示例,以便您更好地理解。
打印(x_test[:10])
幸存的 Pclass Sex SibSp Parch Fare 5 0 3 1 0 0 8.4583 17 1 2 1 0 0 13.0000 19 1 3 0 0 0 7.2250 26 0 3 1 0 0 7.2250 28 1 3 0 0 0 7.8792 29 0 3 1 0 0 7.8958 31 1 1 0 1 0 146.5208 32 1 3 0 0 0 7.7500 36 1 3 1 0
这就是将输入传递给回归模型的方式。 让我们看看预测的年龄值。
打印(y_pred[:10])
[29.07080066 30.10833306 22.44685065 29.08927347 22.43705181 29.07922599 32.43692984 22.43898701 22.15615704 29.07922599
欢呼! 我们得到了值。
分类数据中的缺失值
到现在为止,我们看到了如何处理缺失的数值数据。 如果在分类特征的情况下数据丢失怎么办? 例如,泰坦尼克号数据集的“Cabin”特征是分类的。 在这里,我们无法计算均值和中位数。 因此,我们可以使用模式或最常出现的类/类别来填充缺失值。
train['Cabin']=train['Cabin'].fillna(train['Cabin'].value_counts().index[0])
当缺失值的百分比较小时,首选此方法。 它不会造成大量数据丢失,并且具有统计相关性。
但是,如果您有很多缺失值,那么用最频繁的类进行插补是没有意义的。 相反,让我们为缺失值创建一个单独的类别,例如“未知”或“不可用”。 班级将增加一班。
当缺失值来自分类列(字符串或数字)时,缺失值可以替换为最常见的类别。 如果缺失值的数量非常大,则可以将其替换为新类别。
train['Cabin']=train['Cabin'].fillna('Unknown') train['Cabin'][:10]
它适用于小数据集。 它还通过添加唯一类别来消除数据丢失。
如何处理时间序列数据中的缺失值?
以有序的方式收集信息和时间戳的数据集被表示为时间序列数据。 如果您在时间序列数据中有缺失值,您显然可以尝试上述任何一种方法。 但是也有一些特定的方法可以在这里使用。
为了得到一个想法,我将创建一个简单的虚拟数据集。
time= pd.date_range("1/01/2021", period=10, freq="W") df = pd.DataFrame(index=time); df[“售出单位”] = [5.0,4.0,np.nan,np.nan,1.0,np.nan,3.0,6.0,np.nan,2.0]; 打印(df)
让我们继续讨论方法
前向填充缺失值
下一行的值将用于填充缺失值。'ffill'代表'向前填充'。 这很容易实现。 您只需要在 fillna() 函数中将“method”参数作为“ffill”传递。
forward_filled=df.fillna(method='ffill') 打印(forward_fill)
向后填充缺失值
在这里,我们使用前一行的值来填充缺失值。 'bfill' 代表向后填充。 在这里,您需要传递 'bfill' 作为方法参数。
向后填充 = df.fillna(method='bfill') 打印(向后填充)
我希望您能够通过上面的图片发现两种情况的不同之处。
线性插值
时间序列数据有很多变化。 上述使用回填和向前填充的插补方法并不是最好的解决方案。 线性插值来拯救你!
在这里,这些值填充有递增或递减的值。 它是一种插补技术,试图绘制数据点之间的线性关系。 它使用可用的非空值来计算缺失点。
插值 = df.interpolate(limit_direction="both") 打印(插值)
将这些值与前后填充进行比较,然后自己检查哪个好!
这些是处理时间序列数据中缺失值的一些基本方法
对缺失值鲁棒的算法
在某些情况下,上述方法均无效。 但是,您需要进行分析。 然后,您应该选择支持缺失值的算法。 KNN(K 个最近邻)就是这样一种算法。 它将通过取 K 个最近值中的大多数来考虑缺失值。 随机森林对于具有缺失值的分类数据也很稳健。 许多基于决策树的算法,如 XGBoost、Catboost 都支持缺失值的数据。
结论
总而言之,第一步是探索数据并找出哪些变量缺少数据,百分比是多少,以及它属于哪个类别。 在此之后,您将对可以尝试的方法有一个战略性的想法。 除了线性回归模型之外,一个有用的提示是尝试使用 K 最近邻算法进行插补。 如果上述方法不起作用,您可以查找一些最近的方法,例如使用 Datawig 或 Hot-Deck Imputation 方法。
我希望你喜欢阅读。
您可以通过以下方式与我联系: [电子邮件保护]
LinkedIn: 数据预处理
- '
- 100
- 7
- 77
- 9
- 获得
- 优点
- 算法
- 算法
- 所有类型
- Amazon
- 其中
- 分析
- 分析
- 围绕
- 刊文
- 最佳
- 建筑物
- 呼叫
- 例
- 原因
- 图表
- 分类
- 码
- 柱
- 公司
- 计算
- 腐败
- data
- 数据科学
- 天
- 处理
- DID
- 下降
- 下降
- 事件
- 时尚
- 专栏
- 特征
- 姓氏:
- 适合
- 遵循
- 申请
- 向前
- 功能
- 未来
- 给予
- 指南
- 处理
- 此处
- 创新中心
- How To
- HTTPS
- 巨大
- 主意
- 图片
- 信息
- 网络
- IT
- 知识
- 大
- 铅
- 领导
- 学习
- 自学资料库
- Line
- 主要
- 多数
- 制作
- 地图
- 矩阵
- 衡量
- 媒体
- ML
- 模型
- 移动
- 邻居
- Netflix公司
- 其他名称
- 模式
- 员工
- 平台
- 热门
- 功率
- 预测
- 预测
- 当下
- 蟒蛇
- 量
- 真实的世界
- 原因
- 记录
- 减少
- 回归
- REST的
- 成果
- 科学
- 感
- 系列
- 性生活
- 简易
- 尺寸
- 小
- So
- 社会
- 社会化媒体
- 出售
- 解决
- Spot
- 传播
- 善用
- SUPPORT
- 调查
- 目标
- test
- 测试
- 未来
- 次
- 产品培训
- us
- 折扣值
- 可视化
- W
- 什么是
- WHO
- 工作
- 合作
- 世界
- X
- 年