【问题标题】:How to delete a column in pandas dataframe based on a condition?如何根据条件删除熊猫数据框中的列?
【发布时间】:2015-10-15 09:05:08
【问题描述】:

我有一个 pandas DataFrame,里面有很多 NAN 值。

如何删除 number_of_na_values > 2000 这样的列?

我试着这样做:

toRemove = set()
naNumbersPerColumn = df.isnull().sum()
for i in naNumbersPerColumn.index:
    if(naNumbersPerColumn[i]>2000):
         toRemove.add(i)
for i in toRemove:
    df.drop(i, axis=1, inplace=True)

有更优雅的方法吗?

【问题讨论】:

    标签: python pandas dataframe nan


    【解决方案1】:

    这是另一种保留每列中具有小于或等于指定数量的 nan 的列的方法:

    max_number_of_nas = 3000
    df = df.loc[:, (df.isnull().sum(axis=0) <= max_number_of_nas)]
    

    在我的测试中,在我测试的情况下,这似乎比Jianxun Li 建议的drop columns 方法稍快(如下所示)。但是,我应该注意,如果您根本不使用 apply 方法(例如df.drop(df.columns[df.isnull().sum(axis=0) &gt; max_number_of_nans], axis=1)),性能会变得更加相似。只是提醒一下,当谈到 pandas vectorization almost always wins out over apply 的性能时。

    np.random.seed(0)
    df = pd.DataFrame(np.random.randn(10000,5), columns=list('ABCDE'))
    df[df < 0] = np.nan
    max_number_of_nans = 5010
    
    %timeit c = df.loc[:, (df.isnull().sum(axis=0) <= max_number_of_nans)]
    >> 1.1 ms ± 4.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    %timeit c = df.drop(df.columns[df.isnull().sum(axis=0) > max_number_of_nans], axis=1)
    >> 1.3 ms ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    %timeit c = df.drop(df.columns[df.apply(lambda col: col.isnull().sum() > max_number_of_nans)], axis=1)
    >> 2.11 ms ± 29.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    性能通常因数据大小而异,因此请不要忘记检查最接近您的数据的情况。

    np.random.seed(0)
    df = pd.DataFrame(np.random.randn(10, 5), columns=list('ABCDE'))
    df[df < 0] = np.nan
    max_number_of_nans = 5
    
    %timeit c = df.loc[:, (df.isnull().sum(axis=0) <= max_number_of_nans)]
    >> 755 µs ± 4.84 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    %timeit c = df.drop(df.columns[df.isnull().sum(axis=0) > max_number_of_nans], axis=1)
    >> 777 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    %timeit c = df.drop(df.columns[df.apply(lambda col: col.isnull().sum() > max_number_of_nans)], axis=1)
    >> 1.71 ms ± 17.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    【讨论】:

      【解决方案2】:

      相同的逻辑,但只是将所有内容放在一行中。

      import pandas as pd
      import numpy as np
      
      # artificial data
      # ====================================
      np.random.seed(0)
      df = pd.DataFrame(np.random.randn(10,5), columns=list('ABCDE'))
      df[df < 0] = np.nan
      
              A       B       C       D       E
      0  1.7641  0.4002  0.9787  2.2409  1.8676
      1     NaN  0.9501     NaN     NaN  0.4106
      2  0.1440  1.4543  0.7610  0.1217  0.4439
      3  0.3337  1.4941     NaN  0.3131     NaN
      4     NaN  0.6536  0.8644     NaN  2.2698
      5     NaN  0.0458     NaN  1.5328  1.4694
      6  0.1549  0.3782     NaN     NaN     NaN
      7  0.1563  1.2303  1.2024     NaN     NaN
      8     NaN     NaN     NaN  1.9508     NaN
      9     NaN     NaN  0.7775     NaN     NaN
      
      # processing: drop columns with no. of NaN > 3
      # ====================================
      df.drop(df.columns[df.apply(lambda col: col.isnull().sum() > 3)], axis=1)
      
      
      Out[183]:
              B
      0  0.4002
      1  0.9501
      2  1.4543
      3  1.4941
      4  0.6536
      5  0.0458
      6  0.3782
      7  1.2303
      8     NaN
      9     NaN
      

      【讨论】:

        猜你喜欢
        • 2017-10-04
        • 2021-11-02
        • 1970-01-01
        • 1970-01-01
        • 2022-08-02
        • 1970-01-01
        • 2016-12-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多