【问题标题】:How to select rows with one or more nulls from a pandas DataFrame without listing columns explicitly?如何在不明确列出列的情况下从 pandas DataFrame 中选择具有一个或多个空值的行?
【发布时间】:2012-12-24 05:31:36
【问题描述】:

我有一个约 300K 行和约 40 列的数据框。 我想知道是否有任何行包含空值 - 并将这些“空”行放入单独的数据框中,以便我可以轻松地探索它们。

我可以显式地创建一个掩码:

mask = False
for col in df.columns: 
    mask = mask | df[col].isnull()
dfnulls = df[mask]

或者我可以这样做:

df.ix[df.index[(df.T == np.nan).sum() > 1]]

有没有更优雅的方法(定位带有空值的行)?

【问题讨论】:

    标签: python pandas null nan


    【解决方案1】:
    df1 = df[df.isna().any(axis=1)]
    

    参考链接:(Display rows with one or more NaN values in pandas dataframe)

    【讨论】:

      【解决方案2】:

      少了四个字符,但多了 2 毫秒

      %%timeit
      df.isna().T.any()
      # 52.4 ms ± 352 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
      
      %%timeit
      df.isna().any(axis=1)
      # 50 ms ± 423 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
      

      我可能会使用axis=1

      【讨论】:

        【解决方案3】:

        如果你想通过一定数量的空值列来过滤行,你可以使用这个:

        df.iloc[df[(df.isnull().sum(axis=1) >= qty_of_nuls)].index]
        

        所以,这里是例子:

        您的数据框:

        >>> df = pd.DataFrame([range(4), [0, np.NaN, 0, np.NaN], [0, 0, np.NaN, 0], range(4), [np.NaN, 0, np.NaN, np.NaN]])
        >>> df
             0    1    2    3
        0  0.0  1.0  2.0  3.0
        1  0.0  NaN  0.0  NaN
        2  0.0  0.0  NaN  0.0
        3  0.0  1.0  2.0  3.0
        4  NaN  0.0  NaN  NaN
        

        如果要选择具有两列或多列空值的行,请运行以下命令:

        >>> qty_of_nuls = 2
        >>> df.iloc[df[(df.isnull().sum(axis=1) >=qty_of_nuls)].index]
             0    1    2   3
        1  0.0  NaN  0.0 NaN
        4  NaN  0.0  NaN NaN
        

        【讨论】:

          【解决方案4】:

          .any().all() 非常适用于极端情况,但不适用于查找特定数量的空值。这是一种非常简单的方法来做我相信你问的事情。它非常冗长,但很实用。

          import pandas as pd
          import numpy as np
          
          # Some test data frame
          df = pd.DataFrame({'num_legs':          [2, 4,      np.nan, 0, np.nan],
                             'num_wings':         [2, 0,      np.nan, 0, 9],
                             'num_specimen_seen': [10, np.nan, 1,     8, np.nan]})
          
          # Helper : Gets NaNs for some row
          def row_nan_sums(df):
              sums = []
              for row in df.values:
                  sum = 0
                  for el in row:
                      if el != el: # np.nan is never equal to itself. This is "hacky", but complete.
                          sum+=1
                  sums.append(sum)
              return sums
          
          # Returns a list of indices for rows with k+ NaNs
          def query_k_plus_sums(df, k):
              sums = row_nan_sums(df)
              indices = []
              i = 0
              for sum in sums:
                  if (sum >= k):
                      indices.append(i)
                  i += 1
              return indices
          
          # test
          print(df)
          print(query_k_plus_sums(df, 2))
          

          输出

             num_legs  num_wings  num_specimen_seen
          0       2.0        2.0               10.0
          1       4.0        0.0                NaN
          2       NaN        NaN                1.0
          3       0.0        0.0                8.0
          4       NaN        9.0                NaN
          [2, 4]
          

          那么,如果你和我一样想要清除这些行,你只需写这个:

          # drop the rows from the data frame
          df.drop(query_k_plus_sums(df, 2),inplace=True)
          # Reshuffle up data (if you don't do this, the indices won't reset)
          df = df.sample(frac=1).reset_index(drop=True)
          # print data frame
          print(df)
          

          输出:

             num_legs  num_wings  num_specimen_seen
          0       4.0        0.0                NaN
          1       0.0        0.0                8.0
          2       2.0        2.0               10.0
          

          【讨论】:

            【解决方案5】:
            def nans(df): return df[df.isnull().any(axis=1)]
            

            然后,当您需要时,您可以输入:

            nans(your_dataframe)
            

            【讨论】:

            【解决方案6】:

            [更新以适应现代pandas,其中isnull作为DataFrames..的方法]

            您可以使用isnullany 构建一个布尔系列并使用它来索引到您的框架:

            >>> df = pd.DataFrame([range(3), [0, np.NaN, 0], [0, 0, np.NaN], range(3), range(3)])
            >>> df.isnull()
                   0      1      2
            0  False  False  False
            1  False   True  False
            2  False  False   True
            3  False  False  False
            4  False  False  False
            >>> df.isnull().any(axis=1)
            0    False
            1     True
            2     True
            3    False
            4    False
            dtype: bool
            >>> df[df.isnull().any(axis=1)]
               0   1   2
            1  0 NaN   0
            2  0   0 NaN
            

            [对于老pandas:]

            您可以使用函数isnull 代替方法:

            In [56]: df = pd.DataFrame([range(3), [0, np.NaN, 0], [0, 0, np.NaN], range(3), range(3)])
            
            In [57]: df
            Out[57]: 
               0   1   2
            0  0   1   2
            1  0 NaN   0
            2  0   0 NaN
            3  0   1   2
            4  0   1   2
            
            In [58]: pd.isnull(df)
            Out[58]: 
                   0      1      2
            0  False  False  False
            1  False   True  False
            2  False  False   True
            3  False  False  False
            4  False  False  False
            
            In [59]: pd.isnull(df).any(axis=1)
            Out[59]: 
            0    False
            1     True
            2     True
            3    False
            4    False
            

            导致相当紧凑:

            In [60]: df[pd.isnull(df).any(axis=1)]
            Out[60]: 
               0   1   2
            1  0 NaN   0
            2  0   0 NaN
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-05-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-09-16
              • 1970-01-01
              • 2023-03-30
              相关资源
              最近更新 更多