【问题标题】:Filter out nan rows in a specific column过滤掉特定列中的 nan 行
【发布时间】:2017-10-04 21:56:46
【问题描述】:
df =

Col1 Col2 Col3
1    nan  4
2    5    4
3    3    nan

给定数据框df,我想在Col2 列中获取一个不包含nan 的新数据框df2。这是预期的结果: df2 =

Col1 Col2 Col3
2    5    4
3    3    nan

我知道可以使用pandas.isnulldropna,但是如何仅指定应该应用过滤的特定列?

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    下面的简单实现从上面继承 - 但显示过滤掉特定列中的 nan 行 - 就地 - 并用于 large 数据框按列名计数 nan 的行(之前和之后)

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame([[1,np.nan,'A100'],[4,5,'A213'],[7,8,np.nan],[10,np.nan,'GA23']])
    df.columns = ['areaCode','Distance','accountCode']
    

    数据框

    areaCode    Distance    accountCode
    1           NaN         A100
    4           5.0         A213
    7           8.0         NaN
    10          NaN         GA23
    

    之前:用nan计算行数(每列):

    df.isnull().sum()
    

    按列计数:

    areaCode       0
    Distance       2
    accountCode    1
    dtype: int64
    

    就地删除不需要的行:

    df.dropna(subset=['Distance'],inplace=True)
    

    之后:用 nan 计算行数(每列):

    df.isnull().sum()
    

    按列计数:

    areaCode       0
    Distance       0
    accountCode    1
    dtype: int64
    

    数据框:

    areaCode    Distance    accountCode
    4           5.0         A213
    7           8.0         NaN
    

    【讨论】:

      【解决方案2】:

      如果您想在删除列之前计算和绘制 nan 的数量

      import pandas as pd
      import seaborn as sns
      import matplotlib.pyplot as plt
      
      cols = df.columns
      nans = [df[col].isna().sum() for col in cols] 
      
      sns.set(font_scale=1.1)
      ax = sns.barplot(cols, nans, palette='hls', log=False)
      ax.set(xlabel='Feature', ylabel='Number of NaNs', title='Number of NaNs per feature')
      for p, uniq in zip(ax.patches, nans):
          height = p.get_height()
          ax.text(p.get_x()+p.get_width()/2.,
                  height + 10,
                  uniq,
                  ha="center") 
      ax.set_xticklabels(ax.get_xticklabels(),rotation=90)
      plt.show()
      

      【讨论】:

        【解决方案3】:

        你可以使用DataFrame.dropna()方法:

        In [202]: df.dropna(subset=['Col2'])
        Out[202]:
           Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        或者(在这种情况下)不那么惯用的Series.notnull()

        In [204]: df.loc[df.Col2.notnull()]
        Out[204]:
           Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        或使用DataFrame.query()方法:

        In [205]: df.query("Col2 == Col2")
        Out[205]:
           Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        numexpr解决方案:

        In [241]: import numexpr as ne
        
        In [242]: col = df.Col2
        
        In [243]: df[ne.evaluate("col == col")]
        Out[243]:
           Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        【讨论】:

        • 这是一个很好的答案。整洁!
        【解决方案4】:

        使用numpyisnan来屏蔽并构造一个新的dataframe

        m = ~np.isnan(df.Col2.values)
        pd.DataFrame(df.values[m], df.index[m], df.columns)
        
           Col1  Col2  Col3
        1   2.0   5.0   4.0
        2   3.0   3.0   NaN
        

        时机
        更大的数据

        np.random.seed([3,1415])
        df = pd.DataFrame(np.random.choice([np.nan, 1], size=(10000, 10))).add_prefix('Col')
        
        %%timeit
        m = ~np.isnan(df.Col2.values)
        pd.DataFrame(df.values[m], df.index[m], df.columns)
        1000 loops, best of 3: 326 µs per loop
        
        %timeit df.query("Col2 == Col2")
        1000 loops, best of 3: 1.48 ms per loop
        
        %timeit df.loc[df.Col2.notnull()]
        1000 loops, best of 3: 417 µs per loop
        
        %timeit df[~df['Col2'].isnull()]
        1000 loops, best of 3: 385 µs per loop
        
        %timeit df.dropna(subset=['Col2'])
        1000 loops, best of 3: 913 µs per loop
        

        【讨论】:

        • 能否请您为此解决方案添加时间:import numexpr as ne; col = df.Col2.values; %timeit df[ne.evaluate("col == col")]
        【解决方案5】:

        使用dropna:

        df = df.dropna(subset=['Col2'])
        print (df)
          Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        另一种解决方案 - boolean indexingnotnull

        df = df[df['Col2'].notnull()]
        print (df)
           Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        什么是相同的:

        df = df[~df['Col2'].isnull()]
        print (df)
           Col1  Col2  Col3
        1     2   5.0   4.0
        2     3   3.0   NaN
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-22
          • 2014-06-05
          • 2018-09-02
          • 1970-01-01
          • 2019-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多