【问题标题】:How to remove columns with too many missing values in Python如何在 Python 中删除缺失值过多的列
【发布时间】:2018-01-12 21:04:26
【问题描述】:

我正在研究一个机器学习问题,其中特征中存在许多缺失值。有 100 个特征,我想删除那些缺失值太多的特征(它可能是缺失值超过 80% 的特征)。我如何在 Python 中做到这一点?

我的数据是 Pandas 数据框。

【问题讨论】:

    标签: python pandas dataframe scikit-learn missing-data


    【解决方案1】:

    演示:

    设置:

    In [105]: df = pd.DataFrame(np.random.choice([2,np.nan], (20, 5), p=[0.2, 0.8]), columns=list('abcde'))
    
    In [106]: df
    Out[106]:
          a    b    c    d    e
    0   NaN  2.0  NaN  NaN  NaN
    1   NaN  NaN  2.0  NaN  2.0
    2   NaN  2.0  NaN  NaN  NaN
    3   NaN  NaN  NaN  NaN  2.0
    4   NaN  2.0  2.0  NaN  NaN
    5   NaN  NaN  NaN  NaN  NaN
    6   NaN  2.0  NaN  NaN  NaN
    7   2.0  2.0  NaN  NaN  NaN
    8   2.0  2.0  NaN  NaN  NaN
    9   NaN  NaN  NaN  NaN  NaN
    10  NaN  2.0  2.0  NaN  2.0
    11  NaN  NaN  NaN  2.0  NaN
    12  2.0  NaN  NaN  2.0  NaN
    13  NaN  NaN  NaN  2.0  NaN
    14  NaN  NaN  NaN  2.0  2.0
    15  NaN  NaN  NaN  NaN  NaN
    16  NaN  2.0  NaN  NaN  NaN
    17  2.0  NaN  NaN  NaN  2.0
    18  NaN  NaN  NaN  2.0  NaN
    19  NaN  2.0  NaN  2.0  NaN
    
    In [107]: df.isnull().mean()
    Out[107]:
    a    0.80
    b    0.55
    c    0.85
    d    0.70
    e    0.75
    dtype: float64
    

    解决方案:

    In [108]: df.columns[df.isnull().mean() < 0.8]
    Out[108]: Index(['b', 'd', 'e'], dtype='object')
    
    In [109]: df[df.columns[df.isnull().mean() < 0.8]]
    Out[109]:
          b    d    e
    0   2.0  NaN  NaN
    1   NaN  NaN  2.0
    2   2.0  NaN  NaN
    3   NaN  NaN  2.0
    4   2.0  NaN  NaN
    5   NaN  NaN  NaN
    6   2.0  NaN  NaN
    7   2.0  NaN  NaN
    8   2.0  NaN  NaN
    9   NaN  NaN  NaN
    10  2.0  NaN  2.0
    11  NaN  2.0  NaN
    12  NaN  2.0  NaN
    13  NaN  2.0  NaN
    14  NaN  2.0  2.0
    15  NaN  NaN  NaN
    16  2.0  NaN  NaN
    17  NaN  NaN  2.0
    18  NaN  2.0  NaN
    19  2.0  2.0  NaN
    

    【讨论】:

    • 一如既往的出色解决方案,+1。但是,为了可见性,我会说最好有更多的列而不是行。我也添加了一个行过滤器作为答案。 (或者也许只是我 - 坐在笔记本电脑上)
    【解决方案2】:

    您可以使用 Pandas 的 dropna()

    limitPer = len(yourdf) * .80
    yourdf = yourdf.dropna(thresh=limitPer, axis=1)
    

    【讨论】:

    • 更熊猫风格的解决方案!
    【解决方案3】:

    MaxU's example之后,这是过滤行的选项:

        df = pd.DataFrame(np.random.choice([2,np.nan], (5,10), p=[0.2, 0.8]), columns=list('abcdefghij'))
    
            a    b    c    d    e    f    g    h    i    j
        0   NaN  NaN  NaN  NaN  NaN  2.0  NaN  NaN  NaN  2.0
        1   NaN  2.0  NaN  2.0  NaN  NaN  2.0  NaN  NaN  2.0
        2   NaN  NaN  2.0  NaN  2.0  NaN  2.0  2.0  NaN  NaN
        3   NaN  NaN  NaN  NaN  NaN  2.0  NaN  NaN  NaN  2.0
        4   2.0  2.0  2.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN
    

        df.loc[df.isnull().mean(axis=1).lt(0.8)]
    
            a    b    c    d    e    f    g    h    i    j
        1   NaN  2.0  NaN  2.0  NaN  NaN  2.0  NaN  NaN  2.0
        2   NaN  NaN  2.0  NaN  2.0  NaN  2.0  2.0  NaN  NaN
        4   2.0  2.0  2.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN
    

    【讨论】:

      【解决方案4】:

      要在 Pandas 中进行概括,您可以执行以下操作来计算缺少值的列中值的百分比。您可以从这些列中过滤掉 NULL 值超过 80% 的特征,然后从 DataFrame 中删除这些列。

      pct_null = df.isnull().sum() / len(df)
      missing_features = pct_null[pct_null > 0.80].index
      df.drop(missing_features, axis=1, inplace=True)
      

      【讨论】:

        【解决方案5】:

        这是一个简单的函数,您可以通过传递数据帧和阈值直接使用它

        def rmissingvaluecol(dff, threshold):
            l = []
            l = list(dff.drop(dff.loc[:,list((100*(dff.isnull().sum()/len(dff.index)) >= threshold))].columns, 1).columns.values)
            print("# Columns having more than %s percent missing values: "%threshold, (dff.shape[1] - len(l)))
            print("Columns:\n", list(set(list((dff.columns.values))) - set(l)))
            return l
        
        
        rmissingvaluecol(df,80) # Here threshold is 80% which means we are going to drop columns having more than 80% of missing values
        
        # Output
        '''
        # Columns having more than 60 percent missing values: 2
        Columns:
         ['id', 'location']
        '''
        

        现在创建一个不包括这些列的新数据框:

        l = rmissingvaluecol(df, 49)
        df1 = df[l]
        

        奖励步骤

        您可以找到每列缺失值的百分比(可选)

        def missing(dff):
            print (round((dff.isnull().sum() * 100/ len(dff)),2).sort_values(ascending=False))
        
        missing(df)
        
        # Output
        '''
        id          83.33
        location    83.33
        owner       16.67
        pets        16.67
        dtype: float64
        '''
        

        【讨论】:

          【解决方案6】:

          按列查找 NaN 总和或百分比的最快方法是:

          • 求和:df.isna().sum()
          • 对于百分比:df.isna().mean()

          【讨论】:

            【解决方案7】:
            def show_null_columns(data, agg, threshold):
                if agg == 'sum':
                   null_cols = data.isnull().sum()
                elif agg == 'mean':
                   null_cols = data.isnull().mean()
                columns = data.columns
                null_dic = {}
                for col,x in zip(columns, null_cols):
                    if x>= threshold:
                        null_dic[col] = x
                return null_dic
            
            null_dic = show_null_columns(train, 'mean', 0.8)
            train2 = train.drop(null_dic.keys(), axis=1)
            

            【讨论】:

              【解决方案8】:

              用途:

              df = df[df.isnull().sum(axis=1) <= 5]
              

              这里我们删除缺失值超过五个的行中的缺失值。

              【讨论】:

                【解决方案9】:

                根据文档,关于 dropna() 的一件事, thresh 参数指定要保留的非 NaN 的数量。

                【讨论】:

                • 欢迎来到 StackOverflow。这似乎更像是评论而不是答案。请考虑评论您最喜欢的答案。
                • 我确实尝试过,但我似乎还没有足够的“声誉”。但是,我认为我提到的这一点可以改变 dropna() 的输出。
                • 坚持住。用不了多久你就可以制作 cmets 了。
                • 感谢您的鼓励!
                猜你喜欢
                • 2017-04-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-10-29
                • 2020-05-09
                • 2013-08-16
                • 2019-04-19
                • 1970-01-01
                相关资源
                最近更新 更多