缺失值类型
对缺失值进行填充,或者删除特征列
当单个特征列的缺失值占总样本数的20即以上时,删除该列,否则填充,填充有自定义填充,统计值填充。

定义数据集

  1. import numpy as np
  2. import pandas as pd
  3. # 构造数据
  4. def dataset():
  5. col1 = [1, 2, 3, 4, 5, 6, 7, 8, 9,10]
  6. col2 = [3, 1, 7, np.nan, 4, 0, 5, 7, 12, np.nan]
  7. col3 = [3, np.nan, np.nan, np.nan, 9, np.nan, 10, np.nan, 4, np.nan]
  8. y = [10, 15, 8, 12, 17, 9, 7, 14, 16, 20]
  9. data = {'feature1':col1, 'feature2':col2, 'feature3':col3, 'label':y}
  10. df = pd.DataFrame(data)
  11. return df
  12. data = dataset()
  13. data
feature1 feature2 feature3 label
0 1 3.0 3.0 10
1 2 1.0 NaN 15
2 3 7.0 NaN 8
3 4 NaN NaN 12
4 5 4.0 9.0 17
5 6 0.0 NaN 9
6 7 5.0 10.0 7
7 8 7.0 NaN 14
8 9 12.0 4.0 16
9 10 NaN NaN 20

删除缺失值大于50%的列的函数

  1. def delete_feature(df):
  2. N = df.shape[0] # 样本数
  3. '''先用count数出每一个特征的非空数据数量, 返回的是series,转化成dataframe,不过是\
  4. 竖着的,在转置一下'''
  5. no_nan_count = df.count().to_frame().T
  6. del_feature, save_feature = [], [] # 设置删除列表和保存列表
  7. ''' 非空count的特征列转化成列表,不用转的话是index类型,但也可以运行'''
  8. for col in no_nan_count.columns.tolist():
  9. '''no_nan_count[col]返回的是序列类型,.values返回的是一个只有一个元素的列表
  10. 这里也可以直接用序列的索引df.count()[col],可以直接取出值,不用转来转去'''
  11. loss_rate = (N - no_nan_count[col].values[0])/N # 缺失率
  12. # print(loss_rate)
  13. if loss_rate > 0.5: # 缺失率大于 50% 时,将这一维特征删除
  14. del_feature.append(col)
  15. else:
  16. save_feature.append(col)
  17. return del_feature, df[save_feature]
  18. del_feature, df11 = delete_feature(data)
  19. print(del_feature)
  20. df11

删除样本的函数

DataFrme.dropna(axis=0,how=’any’,thresh=None,subset=None,inplace=False)参数:
axis: 默认axis=0。0为按行删除,1为按列删除
how: 默认 ‘any’。 ‘any’指带缺失值的所有行/列;’all’指清除一整行/列都是缺失值的行/列
thresh: int,保留含有int个非nan值的行
subset: 删除特定列中包含缺失值的行或列
inplace: 默认False,即筛选后的数据存为副本,True表示直接在原数据上更改

  1. def delete_sample(df):
  2. df_ = df.dropna()
  3. return df_
  4. delete_sample(df11)

填充特征列

  1. 对于特征的缺失值,可以根据缺失值所对应的那一维特征的统计值来进行填充。统计值一般泛指平均值、中位数、众数、最大值、最小值等,具体使用哪一种统计值要根据具体问题具体分析。
  2. 注意事项:当特征之间存在很强的类别信息时,需要进行类内统计,效果比直接处理会更好。比如在填充身高时,需要先对男女进行分组聚合之后再进行统计值填充处理(男士的一般平均身高1.70,女士一般1.60)。

    df方法填充

    ```python

    均值填充

    print(df11.mean())
    ‘’’ 返回一个序列 feature1 5.500 feature2 4.875 label 12.800 dtype: float64’’’

df11.fillna(df11.mean()) # 分别把对应的均值填充到各个列中

中位数填充

print(df11.median()) df11.fillna(df11.median())

众数填充

print(df11.mode())

由于众数可能会存在多个,因此返回的是序列而不是一个值

所以在填充众数的时候,我们可以 df11[‘feature’].mode()[0],可以取第一个众数作为填充值

def mode_fill(df): for col in df.columns.tolist(): # 可以不加tolist ‘’’isnull()返回一个序列,空值被置换成True,sum()求True的个数,序列的话返回int 也可以直接用describe的循环来判断是否有缺失值’’’ if df[col].isnull().sum() > 0: # 有缺失值就进行众数填充 df[col] = df[col].fillna(df11[col].mode()[0])

  1. return df

mode_fill(df11)

最大最小值填充

df11.fillna(df11.max()) df11.fillna(df11.min())

  1. <a name="L1uEk"></a>
  2. ## 调包填充(记这个好了)
  3. ```python
  4. from sklearn.impute import SimpleImputer
  5. mean_impute = SimpleImputer(strategy='mean') # median、most_frequent
  6. '''整体填充会变成一个大数组,需要重新转换成DataFrame,所以可以用循环一列一列填充'''
  7. df11 = pd.DataFrame(mean_impute.fit_transform(df11),columns=['feature1','feature2','label'])
  8. df11