如何在Pandas DataFrame中检查任何值是否为NaN

706
在Python Pandas中,检查DataFrame是否有一个或多个NaN值的最佳方法是什么?
我知道函数pd.isnan,但这会返回每个元素的布尔值DataFrame。这篇文章并不能完全回答我的问题。

4
请查看pandas中缺失数据计数的摘要 - LinkBerest
最佳答案: https://dev59.com/5GEh5IYBdhLWcg3wk0Oz#75632616 - Jaya Raghavendra
28个回答

835

jwilner的回答非常准确。我在探索是否有更快的选项,因为根据我的经验,对平坦数组求和比计数更快(奇怪吧)。以下代码看起来更快:

df.isnull().values.any()

在这里输入图片描述

import numpy as np
import pandas as pd
import perfplot


def setup(n):
    df = pd.DataFrame(np.random.randn(n))
    df[df > 0.9] = np.nan
    return df


def isnull_any(df):
    return df.isnull().any()


def isnull_values_sum(df):
    return df.isnull().values.sum() > 0


def isnull_sum(df):
    return df.isnull().sum() > 0


def isnull_values_any(df):
    return df.isnull().values.any()


perfplot.save(
    "out.png",
    setup=setup,
    kernels=[isnull_any, isnull_values_sum, isnull_sum, isnull_values_any],
    n_range=[2 ** k for k in range(25)],
)

df.isnull().sum().sum() 的速度较慢,但它提供了额外的信息--缺失值的数量NaNs


1
感谢提供时间基准。令人惊讶的是,pandas 没有内置此功能。正如 @JGreenwell 的帖子所述,df.describe() 可以做到这一点,但没有直接的函数可用。 - hlin117
2
我刚刚计时了df.describe()函数(不包括找到NaN值)。使用一个1000 x 1000的数组,每次调用需要1.15秒。 - hlin117
3
同时,df.isnull().values.sum()df.isnull().values.flatten().sum()稍微快一些。 - Zero
9
你没有尝试 df.isnull().values.any(),对我来说它比其他方法更快。 - CK1
1
np.isnan(df.values).any() 的速度较快,但对于 object dtype 不起作用。 - Eugene Pakhomov
显示剩余5条评论

235

你有几个选择。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] = np.nan
df.iloc[5,3] = np.nan
df.iloc[7:9,5] = np.nan

现在数据框看起来像这样:

          0         1         2         3         4         5
0  0.520113  0.884000  1.260966 -0.236597  0.312972 -0.196281
1 -0.837552       NaN  0.143017  0.862355  0.346550  0.842952
2 -0.452595       NaN -0.420790  0.456215  1.203459  0.527425
3  0.317503 -0.917042  1.780938 -1.584102  0.432745  0.389797
4 -0.722852  1.704820 -0.113821 -1.466458  0.083002  0.011722
5 -0.622851 -0.251935 -1.498837       NaN  1.098323  0.273814
6  0.329585  0.075312 -0.690209 -3.807924  0.489317 -0.841368
7 -1.123433 -1.187496  1.868894 -2.046456 -0.949718       NaN
8  1.133880 -0.110447  0.050385 -1.158387  0.188222       NaN
9 -0.513741  1.196259  0.704537  0.982395 -0.585040 -1.693810
  • 选项1: df.isnull().any().any() - 这会返回一个布尔值

您已经了解了isnull()函数,它会返回如下的数据框:

       0      1      2      3      4      5
0  False  False  False  False  False  False
1  False   True  False  False  False  False
2  False   True  False  False  False  False
3  False  False  False  False  False  False
4  False  False  False  False  False  False
5  False  False  False   True  False  False
6  False  False  False  False  False  False
7  False  False  False  False  False   True
8  False  False  False  False  False   True
9  False  False  False  False  False  False

如果您使用df.isnull().any(),您可以找到仅具有NaN值的列:

0    False
1     True
2    False
3     True
4    False
5     True
dtype: bool

多加一个.any()将告诉你以上任意一个是否为True

> df.isnull().any().any()
True
  • 选项2df.isnull().sum().sum() - 这会返回一个整数,表示NaN值的总数:

这与.any().any()的操作方式相同,首先给出列中NaN值的总和,然后是这些值的总和:

df.isnull().sum()
0    0
1    2
2    0
3    1
4    0
5    2
dtype: int64

最后,要获取 DataFrame 中 NaN 值的总数:

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

4
为什么不使用.any(axis=None)代替.any().any()? - Georgy

107

查找特定列中存在 NaN 值的行:

nan_rows = df[df['name column'].isnull()]

22
为了找出特定列中没有 NaN 的行:non_nan_rows = df[df['列名'].notnull()] - Elmex80s

67

如果你想知道有多少行出现了“一个或多个NaN”:

df.isnull().T.any().T.sum()

或者,如果您需要提取这些行并对其进行检查:

nan_rows = df[df.isnull().T.any()]

这里的 T 是什么? - WestCoastProjects
.transpose() 的别名 - hobs

58

df.isnull().any().any() 就可以了。


34

超级简单的���法: df.isna().any(axis=None)

从 v0.23.2 开始,你可以使用DataFrame.isna+DataFrame.any(axis=None),其中axis=None指定对整个 DataFrame 进行逻辑缩减。

# Setup
df = pd.DataFrame({'A': [1, 2, np.nan], 'B' : [np.nan, 4, 5]})
df
     A    B
0  1.0  NaN
1  2.0  4.0
2  NaN  5.0

df.isna()

       A      B
0  False   True
1  False  False
2   True  False

df.isna().any(axis=None)
# True

有用的替代品

numpy.isnan
如果你使用较旧版本的 pandas,这是另一个性能良好的选择。

np.isnan(df.values)

array([[False,  True],
       [False, False],
       [ True, False]])

np.isnan(df.values).any()
# True

或者,检查总和:

np.isnan(df.values).sum()
# 2

np.isnan(df.values).sum() > 0
# True

Series.hasnans
您也可以迭代调用Series.hasnans。例如,要检查单个列是否具有NaN值,

df['A'].hasnans
# True

使用带有any的推导式(它是一种短路操作)可以检查任何列是否具有NaN。

any(df[c].hasnans for c in df)
# True

这实际上非常


这可能不是最快的选项,但在2022年它是最可读的选择 :) - Joe

24

在 Hobs 出色的回答基础上,我对 Python 和 Pandas 非常陌生,所以如果我有错误,请指出。

要查找哪些行有 NaN 值:

nan_rows = df[df.isnull().any(1)]

通过指定任何()的轴为1来检查行中是否存在'True',可以执行相同的操作而无需进行转置。


这样可以避免两次转置!喜欢你简洁的 any(axis=1) 简化。 - hobs

21

df成为Pandas DataFrame的名称,并且任何值是numpy.nan都是空值。

  1. 如果您想查看哪些列具有null值,哪些不具有(只需True和False)

df.isnull().any()
  • 如果您只想查看具有空值的列

  • df.loc[:, df.isnull().any()].columns
    
  • 如果您想查看每个列中nulls的数量

    df.isna().sum()
    
  • 如果您想查看每个列中空值的百分比

  • df.isna().sum()/(len(df))*100
    
  • 如果您想查看仅包含空值的列中空值的百分比:

  • df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100
    

    编辑1:

    如果您想直观地查看数据缺失的位置:

    import missingno
    missingdata_df = df.columns[df.isnull().any()].tolist()
    missingno.matrix(df[missingdata_df])
    

    如果你想查看每列中空值的数量...那似乎有些疯狂,为什么不直接使用 df.isna().sum() 呢? - AMC

    11

    由于没有人提到,这里还有另一个变量叫做hasnans

    如果 Pandas Series 中的一个或多个值为 NaN,则df[i].hasnans将输出True,否则输出False。请注意,这不是一个函数。

    适用于 Pandas 版本'0.19.2'和'0.20.2'


    6
    这个答案是错误的。 Pandas Series 有这个属性,但 DataFrame 没有。 如果 df = DataFrame([1,None], columns=['foo']),那么 df.hasnans 会抛出一个 AttributeError,但 df.foo.hasnans 会返回 True - Nathan Thompson

    8
    我一直在使用以下内容并将其强制转换为字符串,然后检查是否为NaN值。
       (str(df.at[index, 'column']) == 'nan')
    

    这让我能够检索序列中的特定值,而不仅仅是返回该值是否包含在序列中。

    1
    使用这个函数是否比pandas.isna()有什么优势? - AMC
    这允许检查单个字段。 - Álvaro

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接