1. 简介
在实际的数据分析和挖掘中,我们经常会遇到数据缺失的情况。这些缺失的数据可能来源于不完整的数据源、数据采集的限制、错误的数据录入或数据存储的问题等。对于这些缺失值的处理,我们需要采取相应的策略来保证在使数据分析和建模时能够具有可靠的性能。Python提供了多种缺失值的处理方式,本文将介绍一些较为流行的方法,如剔除法、插值法、均值填充法、频率填充法等。
2. 缺失值处理方法
2.1 剔除法
剔除法是最简单和最直接的缺失值处理方式,简单地说就是删除含有缺失值的数据。当缺失值对于分析结果影响较小时,这种方法便可用于处理缺失值。
在Python中,用pandas库中的dropna()方法来删除含有缺失值的数据:
import pandas as pd
df = pd.read_csv('data.csv')
df = df.dropna()
注意:默认情况下,dropna()会删除所有含有缺失值的行。如果行的所有值都是缺失的,也会被删除。
2.2 插值法
插值法是一种处理缺失值的传统方法之一。简单来说就是根据已有数据的函数关系或其他规则,在数据中插入缺失值。它比剔除法更加合适,因为它保留了非缺失数据的大部分信息。Python中最常用的插值方法之一是线性插值,用pandas和numpy库中的interpolate()方法进行实现:
import pandas as pd
import numpy as np
df = pd.read_csv('data.csv')
df = df.interpolate()
注意:当数据中包含多个缺失值时,插值法可能会并没有非常精确地填补缺失值,甚至可能导致结果偏差加大。
2.3 均值填充法
均值填充法是一种简单而有效的缺失值填充方法,它依据样本均值估算缺失值。用Pandas库中的fillna()方法实现均值填充法如下:
import pandas as pd
df = pd.read_csv('data.csv')
mean = df['column_name'].mean()
df = df.fillna(mean)
其中column_name指代数据中要填充的列的名称。
2.4 频率填充法
对于一些类别型数据,使用频率填充法是更为常见的做法。它的原理是用最常见的值来替换缺失值。使用mode()方法来获取列的最常见值,然后用fillna()方法将所有缺失值替换为该值:
import pandas as pd
df = pd.read_csv('data.csv')
mode = df['column_name'].mode()[0]
df = df.fillna(mode)
注意:频率填充法仅适用于存在分布不平衡时,即大部分数据中值都为同等值时,缺失值才能用众数(mode)替代。如果数据频率相对保持均衡,该方法将失效。
3. 缺失值检测
在缺失值处理之前,首先需要检查数据是否存在缺失的情况。
3.1 查看缺失值数量
用isnull()方法来检查数据中缺失值的数量,如下所示:
import pandas as pd
df = pd.read_csv('data.csv')
null_num = df.isnull().sum()
用sum()方法来查看数据中缺失值的总数。可以通过下列命令查看每列的缺失值数量:
null_num_per_col = df.isnull().sum(axis = 0) # 每列的缺失值数量
注意:如果数据数量较大,建议加入head()或tail()等限定方法,以避免输出过度冗长完成文件。
3.2 绘制缺失值热图
热图能够更直观地反映数据整体缺失情况。用seaborn库来实现:
import pandas as pd
import seaborn as sns
df = pd.read_csv('data.csv')
sns.heatmap(df.isnull(), cmap = 'YlGnBu_r')
注意:这里需要先安装seaborn库及其依赖包。
4. 缺失值填充前和填充后的效果比较
为了更好地比较各种方法,我们需要对数据进行预处理。
import pandas as pd
import numpy as np
df = pd.read_csv('data.csv')
df = df.dropna() # 使用剔除法删除缺失数据行
df = df.reset_index(drop = True) # 重设索引
df_null = pd.read_csv('data.csv')
df_null = df_null.interpolate() # 使用插值法填补缺失值
df_null = df_null.fillna(df_null.mean()) # 均值填充法填补缺失值
df_null = df_null.fillna(df_null.mode().iloc[0]) # 频率填充法填补缺失值
df_null = df_null.reset_index(drop = True)
# 填充前的数据缺失值信息
null_num_per_col = df_null.isnull().sum(axis=0)
print('填充前的数据缺失值信息:')
print('---------------------------------------------')
print(null_num_per_col)
# 填充后的数据缺失值信息
null_num_per_col_after = df.isnull().sum(axis = 0) # 每列的缺失值数量
print('填充后的数据缺失值信息:')
print('---------------------------------------------')
print(null_num_per_col_after)
下面是剔除法、插值法、均值填充法和频率填充法的效果比较:
import pandas as pd
import numpy as np
df = pd.read_csv('data.csv')
df = df.dropna() # 剔除法处理
df = df.reset_index(drop = True)
df_null = pd.read_csv('data.csv')
df_null = df_null.interpolate() # 插值法处理
df_null = df_null.fillna(df_null.mean()) # 均值填充法处理
df_null = df_null.fillna(df_null.mode().iloc[0]) # 频率填充法处理
df_null = df_null.reset_index(drop = True)
# 统计各列的方差
var_original = np.var(df)
var_dropna = np.var(df)
var_interp = np.var(df_null.interpolate())
var_mean_fill = np.var(df_null.fillna(df_null.mean()))
var_mode_fill = np.var(df_null.fillna(df_null.mode().iloc[0]))
# 比较各种方法的性能差异
print('不同方法处理缺失数据后的各列方差:')
print('=====================================================')
print('原始数据的各列方差:\n', var_original)
print('剔除法处理后各列方差:\n', var_dropna)
print('插值法处理后各列方差:\n', var_interp)
print('均值填充法处理后各列方差:\n', var_mean_fill)
print('频率填充法处理后各列方差:\n', var_mode_fill)
注意: 这里只是作为示例,真实数据可能需要根据具体情况来选择更合适的方法进行处理。
总结
数据中的缺失值经常对数据处理和分析造成困扰,但Python提供了丰富的库,使我们可以方便地使用多种方法来处理缺失值。无论是剔除法、插值法、均值填充法还是频率填充法,都应该根据具体情况选择合适的方法。