缺失值是我们在进行数据分析的时候一个非常棘手的问题,缺失值的产生可能是因为采集数据的时候人为的因素,也有可能是有些特征在以前是不进行统计的,而现在纳入了统计的范围,这个特征在之前年份的数据就是缺失的。我们对缺失值的处理方式有两种:填充删除

查看缺失值

  • df.isnull().mean()*100可以查看整个表中每列的缺失值在整个表的缺失值的占比
  • df.isna().sum().sort_values(ascending=False)/df.shape[0]*100查看整个数据表中的每列中nan值的占比

    isnull将数据变为布尔值,缺失值为True,有数据的False,由于布尔值在运算中被当做(0,1),所以我们用sum()函数可以将所有缺失值的数量加总

  1. missing = df.isnull().sum().sort_values(ascending=False).reset_index()
  2. missing.columns = ['features','missing_num']
  3. missing['percentage'] = missing['missing_num']/train.shape[0]
  • 可以查看整个列表中缺失值数量,并用降序排列
  • 查看每列的缺失值的占比
  • pd.DataFrame(data.isnull().``sum``(), columns=[``'#Null values'``]) 以表格的形式查看缺失值

    1. missing = Train_data.isnull().sum()
    2. missing = missing[missing > 0]
    3. missing.sort_values(inplace=True)
    4. missing.plot.bar()
    • 可以使用可视化的柱状图来顺序查看含有缺失值的列及缺失值各自缺失值的数量

查看有缺失值的行

  1. for i in range(0,len(df)):
  2. if True in (df.isnull().iloc[i]).tolist():
  3. print(i)
  4. else:
  5. pass

将有缺失值的行汇聚到一起称为一个DataFrame

  1. li = []
  2. for i in range(0,len(df)):
  3. if True in (df.isnull().iloc[i]).tolist():
  4. li.append(i)
  5. else:
  6. pass
  7. df.iloc[li,:]

上述的代码要写在一行也可以呃,不推荐😜

  1. df.iloc[[x for x in range(0,len(df)) if True in (df.isnull().iloc[x]).tolist()],:]

上述的代码等价于

  1. df[df.isnull().T.any() == True]

可以在返回的含有缺失值的DataFrame上用颜色标记出缺失值

  1. (df[df.isnull().T.any() == True]
  2. .style
  3. .highlight_null(null_color='skyblue'))

image.png

缺失值填充

在进行缺失值填充之前,我们要决定用什么样的策略进行填充(众数、随机森林填充、平均值填充等等),一般来说,填充文本型的数据,比如性别,职业这些,用众数进行填充。填充数值型的数据,比如身高,体重,收入这类的用平均值或者中位数进行填充。

  • 如果很多列都有缺失值,可以将缺失值的列用作列表设一个变量,再用for循环
  • df[col] = df[col].fillna(df[col].dropna().mode().values[0])由于由缺失值,导致列无法进行运算,想要通过出现频率最多的值填充,首先要删除缺失值,这里使用的是.dropna(),删除缺失值后使用mode()计算出众数
  • **cat_data = cat_data.apply(lambda x:x.fillna(x.value_counts().index[0]))**,使用**apply**配合**lambda**函数可以快速遍历列或每列中的每个数据,进行填充
  • **num_data.fillna(method='ffill', inplace=True)**使用缺失值的上一个值填充
  • **num_data.fillna(method='bfill', inplace=True)**使用缺失值的下一个值填充
  • 对于男女,是否同意这种只有两个值的,用出现最频繁的值(众数)填充比较好
  • **mode_imputer = SimpleImputer(strategy="most_frequent")**在sklearn中的SimpleImputer可以对缺失值进行填充,参数strategy指定的填充策略,可参考语雀缺失值填充
  • train2.loc[train2['gender'].isnull(),'gender'] = train2['gender'].value_counts().index[0]通过loc提取出列,在里面增加了一个布尔值的筛选,
    • 中括号里面的第一个参数是行,通过isnull挑选出了缺失值。
    • 中括号第二个参数是列,这里定位到了gender这一列
    • value_counts将gender这列中各个值出现的次数进行降序排列,通过index行索引挑选出最大的并赋值给变量
  • data``[``'Income'``]`` ``=`` ``data``[``'Income'``]``.``fillna``(``data``[``'Income'``]``.``mean``())使用平均值填充income这列的缺失值
  • df['评价人数'] = df['评价人数'].fillna(df['评价人数'].mean())使用缺失值的上下两个值的均值来填充
  • 有时候我们需要用其他的值来填充某列的缺失值,比如语言这列有缺失值,但是国家这列没有,一般来说认为语言和国家是一致的,所以可以用国家列对应的值来填充,这里用了行内循环和条件

    1. data['lan'] = [data['nation'].iloc[i]
    2. if data['lan'].isnull().iloc[i] == True
    3. else data['lan'].iloc[i]
    4. for i in range(0, len(data))]

    fillna函数

  • 使用.fillna()填充缺失值

    data.fillna({
      'Credit_History': data.Credit_History.mode()[0],
      'Self_Employed': data.Dependents.mode()[0],
      'LoanAmount': data.LoanAmount.median(),
      'Dependents': data.Dependents.mode()[0],
      'Loan_Amount_Term': data.Loan_Amount_Term.mode()[0],
      'Gender': data.Gender.mode()[0],
      'Married': data.Married.mode()[0]
    }, inplace=True)
    

    fillna方法的使用:

  • 在fillna方法中传入一个字典可以快速的对于缺失值进行填充

  • data.loc[:'Age'].values.reshape(-1,1)sklearn,kearas中的fit不接受一维的数据,这个方法可以增维
  • 字符型的数据我们可以用众数填充

    fillna函数使用案例

  • 把所有缺失值替换为指定的值0data_train = data_train.fillna(0)

  • 向用缺失值上面的值替换缺失值data_train = data_train.fillna(axis=0,method='ffill')
  • 纵向用缺失值下面的值替换缺失值,且设置最多只填充两个连续的缺失值data_train = data_train.fillna(axis=0,method='bfill',limit=2)

    删除缺失值

    删除缺失值一般使用drona方法df **=** df[['adj_close', 'log_rtn']]**.**dropna(how **=** 'any')