【建议收藏】机器学习数据预处理(一)——缺失值处理方法(内附代码)

📌引言

大家好呀,我是生鱼同学。从本博文开始,我们就从数据处理到机器模型构建的文章专栏撰写,具体的更新和目录都在文末,感兴趣的同学可以支持一下。

请添加图片描述

在进行机器学习的数据处理时,我们首先要做的就是进行的就是缺失值的相关处理。

在收集到的数据中,通常会存在一些不同程度的数据缺失,如何发现它们以及如何处理它们便成为我们需要处理的第一个问题。

在本文中,我们将会以实际数据为例,以不同方式应对不同类型的数据缺失情况。

📌发现缺失值

想要处理缺失值,首先需要我们发现数据的缺失。

这里就需要我们观察到缺失值的同时,利用统计手段观察不同数据缺失的类型,以方便我们初步制定后续数据处理方案。

当然,为了更好的展示缺失情况,这部分还会存在一些缺失可视化的内容。话不多说,我们开始吧。

(下面的数据来自Kaggle泰坦尼克存活预测数据,链接将会在文末)

🏷️加载数据及初步观察

首先加载数据集,然后调用相关函数对其进行初步观察。代码如下:

# 载入数据
data = pd.read_csv('train.csv', index_col=0)

调用 info()和 describe()进行初步的数据观察。代码和结果如下所示:

data.info()

结果如下所示:
在这里插入图片描述
在上图中,我们可以看到Cabin和Age存在一定程度的缺失情况。与此同时,Ticket、Name、Sex都是object的类别,可能在后续的数据处理中需要我们进行编码。

data.describe()

结果如下:
在这里插入图片描述
我们可以发现,上述有几中特征的频率存在一定的偏向,所以我们在后续的数据处理中需要注意。

🏷️缺失值可视化

缺失值可视化是我们不可忽视的重要部分,想要更好的表现出我们的分析结果,就需要我们借助一些可视化的工具来更好地展现出各类分析情况。

当然,缺失值可视化也有很多种方式,包括柱状图、矩阵图等,下面我们分别介绍几种不同的缺失值可视化的方法。

📄柱状图可视化缺失值

首先,我们尝试使用柱状图可视化缺失值,具体代码如下:

# 统计缺失值
missing = data.isnull().sum()
# 筛选出大于0的属性
missing = missing[missing>0]
# 排序
missing.sort_values(inplace=True)
missing.plot.bar()

在这里插入图片描述

📄missingno矩阵图可视化缺失值

missingno 是一个可以将缺失值情况进行可视化的库,十分便捷,下面我们使用此库进行缺失值的可视化。

import missingno as msno
# 在数据中抽样100个单位
data_sample = data.sample(100)
msno.matrix(data_sample)

在这里插入图片描述

📄missingno柱状图可视化缺失值

data_sample = data.sample(100)
msno.bar(data_sample)

在这里插入图片描述

📌缺失值处理

数据预处理对于我们最终模型的效果的提高具有很重要的作用,其中缺失值处理是我们首先要考虑的问题。

数据缺失的原因也有很多种,我们在处理缺失值之前要根据不同的情况选择不同的处理方式,做到灵活运用各种方法。数据缺失的原因主要有以下两种:

  • 随机缺失:由于采集数据不完全导致的数据缺失,这种缺失是相对随机的。
  • 非随机缺失:业务逻辑上的缺失,可能是周期性缺失,或者在业务逻辑上分析确实存在缺失问题。

下面是几种常见的缺失值处理方法,我们需要根据实际情况选择。

🏷️不处理缺失值

  • 优点:不用考虑缺失值的情况,直接忽悠,节省时间。
  • 缺点:只适用于有限的模型。

这种情况只适用于一些特殊模型,如KNN、决策树、随机森林、神经网络、朴素贝叶斯、DBSCAN等。

因为上述几种类型对于数据的缺失值有很强的包容度,所以我们可以不必处理缺失值,把它当作一种类别。

🏷️删除缺失缺失值

  • 优点:简单粗暴
  • 缺点:当缺失值的占比较大时,可能会导致很多关键信息被忽略,可能会影响最终的模型拟合效果。

首先我们统计一下本文例数据的缺失值个数:

missing = data.isnull().sum()
missing = missing[missing>0]
missing

在这里插入图片描述

上述几个属性的缺失值中,Cabin缺失值达到了687个,因为其占比较多所以我们可以考虑把其删除。

代码如下:

# inplace表示是否在原数据进行填充
data.dropna(axis=0, how='any',subset=['Cabin'], inplace=True)

dropna 参数:
axis: default 0指行,1为列
how: {‘any’, ‘all’}, default ‘any’指带缺失值的所有行;'all’指清除全是缺失值的
thresh: int,保留含有int个非空值的行
subset: 对特定的列进行缺失值删除处理
inplace: 这个很常见,True表示直接在原数据上更改

其他的数据我们就可以考虑对其进行其他处理,通过不同方式进行填充。

🏷️缺失值填充

缺失值的填充方式非常多,本文主要介绍几种常用的缺失值填充方法。

📄手动填充

这部分我认为是相对来说最有效的方法,就是根据专业的知识水平判断该种情况的数值。
但是此种填充方法需要的专业性比较强,大多数情况下,我们使用这种方法的能力有限。

📄统计量填充

根据业务逻辑以及各特征的不同含义进行分析,使用平均数,众数,中位数等直接对缺失部分进行填充。

平均值填充

这里以上述数据举例,例如上述数据中的年龄,基本可以进行平均数填充。具体代码如下:

data['Age'].fillna(data['Age'].mean().values[0], inplace=True)

当数据近正态分布的时候,所有观测值都较好的聚集在平均值周围,这时适合填充平均值。

平均数更多的针对连续的类型填充,例如如果某属性表示一个产品的价格,那么我们可以对缺失值填充该属性其它值的平均数。

中位数填充

data['Age'].fillna(data['Age'].median().values[0], inplace=True)

偏态分布和有离群点的分布,可以使用中位数填充。

偏态分布的大部分值都聚集在变量分布的一侧,中位数可以很好的表示中心趋势。

众数填充

train_data['fuelType'].fillna(train_data['fuelType'].mode().values[0], inplace=True)

名义变量更适用于填充众数,因为此种属性一般没有大小且顺序,可以填充众数。

众数更多的针对于某种类别的填充。

📄统计量填充选择指南

我们主要针对不同的情况选择不同的统计填充。我们要根据不同数据特征的具体情况选择不同的统计填充,主要有以下几种:

  • 平均值填充:最好验证一下数据特征是否符合正态分布,可以使用QQ图展示,或者直接一个直方图怼上去,后面我会撰写相关文章介绍相关内容。
  • 中位数填充:有时候数据不符合正态分布,但是其基本是规律的。我们就观察其是否是某种偏态分布,因为数据是集中在中位数附近的,所以我们可以填充中位数。
  • 众数填充:某些类别变量缺失时,我们可以使用众数填充。
  • 其它:上述所有的填充方法一定要结合我们实际的先验知识,由于数据采样的不均衡,很有可能特征表面上看是不符合某种分布的。但是实际上这类数据我们明确的知道他就是正态分布,我们就可以使用相关手段填充。更多的,有些时候某些数据不符合正态分布时候,我们可以先对特征进行一些变化,例如对数变化等。这里就涉及到特征工程的内容,这里就不再赘述了。

📄多重插值

考虑该数据前后类似数据的填充,适合时序特征,随着时间变化的数据的填充,这里的填充是需要我们观察特征的具体变化情况选择某种方式。
例如:

# 向后填充线性插值
data.interpolate(method='linear', limit_direction='backward', axis=0)

DataFrame.interpolate(self, method=‘linear’, axis=0, limit=None, inplace=False, limit_direction=‘forward’, limit_area=None, downcast=None, **kwargs)

  • method:{“线性”,“时间”,“索引”,“值”,“最近”,“零”,“线性”,“二次”,“三次”,“重心”,“克罗格”,“多项式”,“样条”,“ piecewise_polynomial”,“ from_derivatives”,“ pchip”,“ akima”}
  • limit_direction:{“前进”,“后退”,“两者”},默认为“前进”
  • inplace:如果可能,更新NDFrame。

📄建模预测

使用不同的模型对缺失值进行预测,下面使用KNN近邻方法对缺失的值进行预测,这部分有两种实现方法,首先是sklearn的实现:

import sklearn
# 创建该属性的存在部分作为训练集,不存在部分作为测试集
known_train_data = train_data[train_data.fuelType.notnull()]
unknown_train_data = train_data[train_data.fuelType.isnull()]
#选择目标属性作为训练集的y
y = known_train_data.loc[:, 'fuelType']
y_train = np.array(y)
#选择其它属性作为训练集的x
x = known_train_data.loc[:, 'v_1':]
x_train = np.array(x)
#在不存在的部分作为测试集
x_test = np.array(unknown_train_data.loc[:, 'v_1':])
y_test = np.array(unknown_train_data.loc[:, 'fuelType'])
#使用KNN模型进行预测,n_neighbors表示邻居个数
clf = sklearn.neighbors.KNeighborsClassifier(n_neighbors = 14, weights = "distance").fit(x_train,y_train)

test = clf.predict(x_test)
test

后边看了一下分布,整得不错,看来比较适合KNN拟合,但是要根据目标的情况改换成分类或者回归模型。

使用fancyimpute也能够帮我们完成这部分工作,当然其还提供了很多其他方法:
(这个方法我没调用成功,可能是因为有空值)

from fancyimpute import KNN, NuclearNormMinimization, SoftImpute, IterativeImputer, BiScaler
X_filled_knn = KNN(k=3).fit_transform(X_incomplete)

📄高维映射

将属性映射到高维空间,例如某属性表示性别存在部分缺失,我们直接映射到高维表示为三个离散属性分别是,是否男,是否女,是否缺失。
(若属性为连续变量,可选择先进行分箱再做后续处理。)

# train_data['notRepairedDamage'] = train_data['notRepairedDamage'].apply(pd.to_numeric, errors='coerce')
#创建两列新变量
train_data['notRepairedDamage_yes'] = 0
train_data['notRepairedDamage_none'] = 0
#train_data['notRepairedDamage_no'] = 0

# train_data.loc[ (train_data[lambda x:x['notRepairedDamage'] == 1.0]['notRepairedDamage']), 'notRepairedDamage_yes' ] = 1
# train_data.loc[ (train_data[lambda x:x['notRepairedDamage'] == 0.0]['notRepairedDamage']), 'notRepairedDamage_no' ] = 1

train_data.loc[ (train_data.notRepairedDamage.isnull()), 'notRepairedDamage_none' ] = 1
train_data.loc[ (train_data.notRepairedDamage.notnull()), 'notRepairedDamage_yes' ] = 1

print(train_data['notRepairedDamage_yes'].value_counts())
train_data['notRepairedDamage_none'].value_counts()

但是此种方法会提高我们的数据集维度,只有在样本量非常大的时候效果还好,否则会因为数据过于稀疏,效果很差。

📘总结

本次文章介绍了几种常用的缺失值填充的方法,还需要多实践多做相关工作,才能信手拈来。当然还有很多更复杂的方法,大家根据自己的业务逻辑灵活选择。

另外,从数据处理到构建高效模型系列已经全部更新完毕,感兴趣的朋友可以点击下列链接进行支持一下:

  • 13
    点赞
  • 136
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: 以下是 Python 中检查数据集是否存在缺失值的代码: ```python import pandas as pd # 读取数据集 df = pd.read_csv('data.csv') # 检查每一列是否存在缺失值 print(df.isnull().any()) ``` 这段代码使用了 Pandas 库读取数据集,并使用 `.isnull().any()` 方法检查每一列是否存在缺失值。如果某一列存在缺失值,输出结果为 `True`,否则为 `False`。 ### 回答2: 编写一个程序来检查数据集中是否存在缺失值是一项非常常见且重要的任务。下面是一个简单的程序示例,可以用于检查数据集中是否存在缺失值: ```python import pandas as pd def check_missing_values(data): # 检查数据集中是否存在缺失值 missing_values = data.isnull().sum() # 计算缺失值的总数 total_missing = missing_values.sum() # 如果存在缺失值,则输出相应的信息 if total_missing > 0: print("数据集中存在缺失值:") # 输出各个变量的缺失值个数 print(missing_values) # 输出缺失值的总数 print("缺失值总数:", total_missing) else: print("数据集中不存在缺失值。") # 读取数据集 data = pd.read_csv("data.csv") # 检查数据集中是否存在缺失值 check_missing_values(data) ``` 这个程序使用了Pandas库来读取数据集,并通过`isnull().sum()`函数来计算每个变量(列)中的缺失值个数。如果缺失值的总数大于0,则会输出每个变量的缺失值个数以及缺失值的总数;反之,则会输出“数据集中不存在缺失值”这个信息。 需要注意的是,这只是一个简单的程序示例,如果数据集比较复杂或者对缺失值有更详细的处理需求,可能需要进一步完善程序。 ### 回答3: 检查数据集中是否存在缺失值是数据预处理的一个重要步骤,下面是一个用Python编写的程序来实现这个功能。 首先,我们假设数据集以csv文件的形式存在,文件名为"data.csv"。程序如下: ```python import pandas as pd #读取数据集 df = pd.read_csv("data.csv") #检查是否存在缺失值 missing_values = df.isnull().sum() #打印缺失值统计结果 print(missing_values) ``` 在上述程序中,我们首先使用pandas库中的`read_csv`函数来读取数据集。然后,使用`isnull()`函数对数据集进行逐个元素的遍历,如果元素为缺失值,则返回True,否则返回False。接着,使用`sum()`函数对每一列的缺失值个数进行统计。最后,使用`print()`函数打印出统计结果。 如果希望将缺失值个数统计结果保存到一个文件中,可以将最后一行改为: ```python missing_values.to_csv("missing_values.csv", header=False) ``` 这样,缺失值个数统计结果将以csv文件的形式保存在"missing_values.csv"文件中。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

复杂网络

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值