【问题标题】:Best way to count the number of rows with missing values in a pandas DataFrame计算pandas DataFrame中缺失值行数的最佳方法
【发布时间】:2015-03-27 18:46:20
【问题描述】:

我目前想出了一些解决方法来计算 pandas DataFrame 中缺失值的数量。这些都很丑,我想知道是否有更好的方法。

让我们创建一个示例DataFrame

from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
               columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

我目前拥有的是

a) 计数缺失值的单元格:

>>> sum(df.isnull().values.ravel())
9

b) 计算某处缺失值的行数:

>>> sum([True for idx,row in df.iterrows() if any(row.isnull())])
3

【问题讨论】:

  • 关于计算某处缺失值的行数:len(df) - len(df.dropna())

标签: python pandas missing-data


【解决方案1】:

对于第二个计数,我认为只需从dropna 返回的行数中减去行数:

In [14]:

from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
               columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
df
Out[14]:
        one       two     three
a -0.209453 -0.881878  3.146375
b       NaN       NaN       NaN
c  0.049383 -0.698410 -0.482013
d       NaN       NaN       NaN
e -0.140198 -1.285411  0.547451
f -0.219877  0.022055 -2.116037
g       NaN       NaN       NaN
h -0.224695 -0.025628 -0.703680
In [18]:

df.shape[0] - df.dropna().shape[0]
Out[18]:
3

第一个可以使用内置方法实现:

In [30]:

df.isnull().values.ravel().sum()
Out[30]:
9

时间安排

In [34]:

%timeit sum([True for idx,row in df.iterrows() if any(row.isnull())])
%timeit df.shape[0] - df.dropna().shape[0]
%timeit sum(map(any, df.apply(pd.isnull)))
1000 loops, best of 3: 1.55 ms per loop
1000 loops, best of 3: 1.11 ms per loop
1000 loops, best of 3: 1.82 ms per loop
In [33]:

%timeit sum(df.isnull().values.ravel())
%timeit df.isnull().values.ravel().sum()
%timeit df.isnull().sum().sum()
1000 loops, best of 3: 215 µs per loop
1000 loops, best of 3: 210 µs per loop
1000 loops, best of 3: 605 µs per loop

所以对于这种大小的 df,我的替代方案要快一些

更新

因此,对于具有 80,000 行的 df,我得到以下信息:

In [39]:

%timeit sum([True for idx,row in df.iterrows() if any(row.isnull())])
%timeit df.shape[0] - df.dropna().shape[0]
%timeit sum(map(any, df.apply(pd.isnull)))
%timeit np.count_nonzero(df.isnull())
1 loops, best of 3: 9.33 s per loop
100 loops, best of 3: 6.61 ms per loop
100 loops, best of 3: 3.84 ms per loop
1000 loops, best of 3: 395 µs per loop
In [40]:

%timeit sum(df.isnull().values.ravel())
%timeit df.isnull().values.ravel().sum()
%timeit df.isnull().sum().sum()
%timeit np.count_nonzero(df.isnull().values.ravel())
1000 loops, best of 3: 675 µs per loop
1000 loops, best of 3: 679 µs per loop
100 loops, best of 3: 6.56 ms per loop
1000 loops, best of 3: 368 µs per loop

实际上np.count_nonzero 赢得了这场胜利。

【讨论】:

  • 我认为您对计算有某处缺失值的行数的答案可以去掉shape,而可以只做len(df) - len(df.dropna())
【解决方案2】:

总失踪:

df.isnull().sum().sum()

缺失的行:

sum(map(any, df.isnull()))

【讨论】:

    【解决方案3】:

    numpy.count_nonzero呢:

     np.count_nonzero(df.isnull().values)   
     np.count_nonzero(df.isnull())           # also works  
    

    count_nonzero 非常快。但是,我从 (1000,1000) 数组构建了一个数据框,并在不同位置随机插入了 100 个 nan 值,并测量了 iPython 中各种答案的时间:

    %timeit np.count_nonzero(df.isnull().values)
    1000 loops, best of 3: 1.89 ms per loop
    
    %timeit df.isnull().values.ravel().sum()
    100 loops, best of 3: 3.15 ms per loop
    
    %timeit df.isnull().sum().sum()
    100 loops, best of 3: 15.7 ms per loop
    

    与原来的 OP 相比,时间改进不是很大,但在代码中可能不会那么混乱,由您决定。执行时间实际上没有任何差异 在两个count_nonzero 方法之间(有和没有.values)。

    【讨论】:

    【解决方案4】:

    一种计算行或列中缺失值的简单方法

    df.apply(lambda x: sum(x.isnull().values), axis = 0) # For columns
    df.apply(lambda x: sum(x.isnull().values), axis = 1) # For rows
    

    至少有一个缺失值的行数:

    sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
    

    【讨论】:

      【解决方案5】:

      sum(df.count(axis=1) < len(df.columns)),非空值少于列的行数。

      例如,以下数据框有两行缺失值。

      >>> df = pd.DataFrame({"a":[1, None, 3], "b":[4, 5, None]})
      >>> df
          a   b
      0   1   4
      1 NaN   5
      2   3 NaN
      >>> df.count(axis=1)
      0    2
      1    1
      2    1
      dtype: int64
      >>> df.count(axis=1) < len(df.columns)
      0    False
      1     True
      2     True
      dtype: bool
      >>> sum(df.count(axis=1) < len(df.columns))
      2
      

      【讨论】:

        【解决方案6】:

        这里有很多错误的答案。 OP 要求提供空值的行数,而不是列数。

        这是一个更好的例子:

        from numpy.random import randn
        df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],columns=['one','two', 'three'])
        df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','asdf'])
        print(df)
        

        `现在显然有 4 行具有空值。

                   one       two     three
        a    -0.571617  0.952227  0.030825
        b          NaN       NaN       NaN
        c     0.627611 -0.462141  1.047515
        d          NaN       NaN       NaN
        e     0.043763  1.351700  1.480442
        f     0.630803  0.931862  1.500602
        g          NaN       NaN       NaN
        h     0.729103 -1.198237 -0.207602
        asdf       NaN       NaN       NaN
        

        如果您在此处使用了一些答案,您将得到 3(包含 NaN 的列数)的答案。富恩特斯的回答有效。

        我是这样得到的:

        df.isnull().any(axis=1).sum()
        #4
        timeit df.isnull().any(axis=1).sum()
        #10000 loops, best of 3: 193 µs per loop
        

        '富恩特斯':

        sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
        #4
        timeit sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
        #1000 loops, best of 3: 677 µs per loop
        

        【讨论】:

          【解决方案7】:

          我想如果你只是想看看结果,有一个 pandas func pandas.DataFrame.count

          回到这个话题,使用df.count(axis=1),你会得到这样的结果:

          a    3
          b    0
          c    3
          d    0
          e    3
          f    3
          g    0
          h    3
          dtype: int64
          

          它会告诉你每行有多少个非 NaN 参数。同时, -(df.count(axis=1) - df.shape[1]) 表示

          a    0
          b    3
          c    0
          d    3
          e    0
          f    0
          g    3
          h    0
          dtype: int64
          

          【讨论】:

            【解决方案8】:

            关于计算接受的答案提供的某处缺失值的行数

            df.shape[0] - df.dropna().shape[0]
            

            但我宁愿做更直观的(我也认为计算速度更快,至少这是我读过的)

            len(df) - len(df.dropna())
            

            【讨论】:

              【解决方案9】:
              # TOTAL number of missing values:
              >>> df.isna().sum().sum()
              9
              
              # number of ROWS with at least one missing value:
              >>> (df.isna().sum(axis=1) > 0).sum()
              3
              
              # number of COLUMNS with at least one missing value:
              >>> (df.isna().sum(axis=0) > 0).sum()
              3
              

              在此示例中,缺失值的行数和列数是相同的,但不要让您感到困惑。重点是在第一个sum() 方法中使用axis=1axis=0。如果您想查看哪些行包含任何缺失的记录:

              >>> df[(df.isna().sum(axis=1) > 0)]
              
              one two three
              b   NaN NaN NaN
              d   NaN NaN NaN
              g   NaN NaN NaN
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2019-10-18
                • 1970-01-01
                • 1970-01-01
                • 2019-07-17
                • 2012-07-01
                • 2022-01-07
                • 2015-07-15
                • 1970-01-01
                相关资源
                最近更新 更多