正文
这方面没有统一的解决方案。我们必须研究特定特征和数据集,据此决定处理缺失数据的最佳方式。
下面介绍了四种最常用的缺失数据处理方法。不过,如果情况较为复杂,我们需要创造性地使用更复杂的方法,如缺失数据建模。
在统计学中,该方法叫做成列删除(listwise deletion),需要丢弃包含缺失值的整列观察值。
只有在我们确定缺失数据无法提供信息时,才可以执行该操作。否则,我们应当考虑其他解决方案。
例如,从缺失数据直方图中,我们可以看到只有少量观察值的缺失值数量超过 35。因此,我们可以创建一个新的数据集 df_less_missing_rows,该数据集删除了缺失值数量超过 35 的观察值。
# drop rows with a lot of missing values.
ind_missing = df[df['num_missing'] > 35].index
df_less_missing_rows = df.drop(ind_missing, axis=0)
与解决方案 1 类似,我们只在确定某个特征无法提供有用信息时才丢弃它。
例如,从缺失数据百分比列表中,我们可以看到 hospital_beds_raion 具备较高的缺失值百分比——47%,因此我们丢弃这一整个特征。
# hospital_beds_raion has a lot of missing.
# If we want to drop.
cols_to_drop = ['hospital_beds_raion']
df_less_hos_beds_raion = df.drop(cols_to_drop, axis=1)
当特征是数值变量时,执行缺失数据填充。对同一特征的其他非缺失数据取平均值或中位数,用这个值来替换缺失值。
当特征是分类变量时,用众数(最频值)来填充缺失值。
以特征 life_sq 为例,我们可以用特征中位数来替换缺失值。
# replace missing values with the median.
med = df['life_sq'].median()
print(med)
df['life_sq'] = df['life_sq'].fillna(med)
此外,我们还可以对所有数值特征一次性应用同样的填充策略。
# impute the missing values and create the missing value indicator variables for each numeric column.
df_numeric = df.select_dtypes(include=[np.number])
numeric_cols = df_numeric.columns.values
for col in numeric_cols:
missing = df[col].isnull()
num_missing = np.sum(missing)
if num_missing > 0:
print('imputing missing values for: {}'.format(col))
df['{}_ismissing'.format(col)] = missing
med = df[col].median()
df[col] = df[col].fillna(med)
很幸运,本文使用的数据集中的分类特征没有缺失值。不然,我们也可以对所有分类特征一次性应用众数填充策略。
# impute the missing values and create the missing value indicator variables for each non-numeric column.
df_non_numeric = df.select_dtypes(exclude=[np.number])
non_numeric_cols = df_non_numeric.columns.values
for col in non_numeric_cols:
missing = df[col].isnull()
num_missing = np.sum(missing)
if num_missing > 0:
print('imputing missing values for: {}'.format(col))
df['{}_ismissing'.format(col)] = missing
top = df[col].describe()['top']
df[col] = df[col].fillna(top)
对于分类特征,我们可以添加新的带值类别,如 _MISSING_。对于数值特征,我们可以用特定值(如-999)来替换缺失值。
这样,我们就可以保留缺失值,使之提供有价值的信息。
# categorical
df['sub_area'] = df['sub_area'].fillna('_MISSING_')
# numeric
df['life_sq'] = df['life_sq'].fillna(-999)
异常值指与其他观察值具备显著差异的数据,它们可能是真的异常值也可能是错误。
根据特征的属性(数值或分类),使用不同的方法来研究其分布,进而检测异常值。
当特征是数值变量时,使用直方图和箱形图来检测异常值。
df['life_sq'].hist(bins=100)
由于数据中可能存在异常值,因此下图中数据高度偏斜。