【问题标题】:How to check if any value is NaN in a Pandas DataFrame如何检查 Pandas DataFrame 中的任何值是否为 NaN
【发布时间】:2015-06-14 07:56:31
【问题描述】:

在 Python Pandas 中,检查 DataFrame 是否具有一个(或多个)NaN 值的最佳方法是什么?

我知道函数pd.isnan,但这会为每个元素返回一个布尔值的DataFrame。 This post 这里也没有完全回答我的问题。

【问题讨论】:

标签: python pandas dataframe nan


【解决方案1】:

df.isnull().any().any() 应该这样做。

【讨论】:

    【解决方案2】:

    您有几个选择。

    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
    
    • 选项 1df.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
    

    【讨论】:

    • 为什么不用.any(axis=None) 而不是.any().any()
    【解决方案3】:

    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 的数量。

    【讨论】:

    • 感谢您提供时间基准。令人惊讶的是pandas 没有内置函数。从@JGreenwell 的帖子来看,df.describe() 确实可以做到这一点,但没有直接的功能。
    • 我刚刚计时了df.describe()(没有找到NaNs)。使用 1000 x 1000 数组,单个调用需要 1.15 秒。
    • :1,另外,df.isnull().values.sum()df.isnull().values.flatten().sum() 快一点
    • 啊,很好 @JohnGalt -- 我将更改我的解决方案以删除 .flatten() 以进行张贴。谢谢。
    • 你没有尝试df.isnull().values.any(),对我来说它比其他人更快。
    【解决方案4】:

    根据您处理的数据类型,您还可以在执行 EDA 时通过将 dropna 设置为 False 来获取每列的值计数。

    for col in df:
       print df[col].value_counts(dropna=False)
    

    适用于分类变量,但当您有许多唯一值时则效果不佳。

    【讨论】:

    • 我认为这是低效的。 pandas 的内置功能更加简洁。避免 ipython 笔记本混乱。
    【解决方案5】:

    如果您需要知道“一个或多个NaNs”有多少行:

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

    或者如果您需要提取这些行并检查它们:

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

    【讨论】:

      【解决方案6】:

      由于pandas 必须为DataFrame.dropna() 找出这一点,我看了一下他们是如何实现它的,发现他们使用了DataFrame.count(),它计算DataFrame 中的所有非空值.参照。 pandas source code。我没有对这项技术进行基准测试,但我认为库的作者可能已经做出了明智的选择。

      【讨论】:

        【解决方案7】:

        由于没有人提及,所以只有另一个变量名为hasnans

        df[i].hasnans 将输出到 True 如果 pandas 系列中的一个或多个值是 NaN,如果不是,则输出到 False。请注意,它不是函数。

        熊猫版本“0.19.2”和“0.20.2”

        【讨论】:

        • 这个答案不正确。 Pandas 系列有这个属性,但 DataFrames 没有。如果df = DataFrame([1,None], columns=['foo']),则df.hasnans 将抛出AttributeError,但df.foo.hasnans 将返回True
        【解决方案8】:

        添加到 Hobs 的精彩回答,我对 Python 和 Pandas 很陌生,所以如果我错了,请指出。

        要找出哪些行有 NaN:

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

        将执行相同的操作而无需转置,方法是将 any() 的轴指定为 1 以检查行中是否存在“真”。

        【讨论】:

        • 这去掉了两个转置!喜欢你简洁的any(axis=1) 简化。
        【解决方案9】:

        只是使用 math.isnan(x),如果 x 是 NaN(不是数字)则返回 True,否则返回 False。

        【讨论】:

        • x 是一个DataFrame 时,我认为math.isnan(x) 不会起作用。你会得到一个 TypeError 。
        • 你为什么要使用它而不是任何替代品?
        【解决方案10】:

        要找出特定列中哪些行具有 NaN:

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

        【讨论】:

        • 要找出特定列中哪些行没有 NaN:non_nan_rows = df[df['name column'].notnull()]
        【解决方案11】:

        或者您可以在DF 上使用.info(),例如:

        df.info(null_counts=True) 返回列中的非空行数,例如:

        <class 'pandas.core.frame.DataFrame'>
        Int64Index: 3276314 entries, 0 to 3276313
        Data columns (total 10 columns):
        n_matches                          3276314 non-null int64
        avg_pic_distance                   3276314 non-null float64
        

        【讨论】:

          【解决方案12】:

          这是另一种有趣的查找 null 并替换为计算值的方法

              #Creating the DataFrame
          
              testdf = pd.DataFrame({'Tenure':[1,2,3,4,5],'Monthly':[10,20,30,40,50],'Yearly':[10,40,np.nan,np.nan,250]})
              >>> testdf2
                 Monthly  Tenure  Yearly
              0       10       1    10.0
              1       20       2    40.0
              2       30       3     NaN
              3       40       4     NaN
              4       50       5   250.0
          
              #Identifying the rows with empty columns
              nan_rows = testdf2[testdf2['Yearly'].isnull()]
              >>> nan_rows
                 Monthly  Tenure  Yearly
              2       30       3     NaN
              3       40       4     NaN
          
              #Getting the rows# into a list
              >>> index = list(nan_rows.index)
              >>> index
              [2, 3]
          
              # Replacing null values with calculated value
              >>> for i in index:
                  testdf2['Yearly'][i] = testdf2['Monthly'][i] * testdf2['Tenure'][i]
              >>> testdf2
                 Monthly  Tenure  Yearly
              0       10       1    10.0
              1       20       2    40.0
              2       30       3    90.0
              3       40       4   160.0
              4       50       5   250.0
          

          【讨论】:

            【解决方案13】:

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

            Starting from 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 的理解(这是一个短路操作)。

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

            这实际上非常快。

            【讨论】:

              【解决方案14】:
              df.apply(axis=0, func=lambda x : any(pd.isnull(x)))
              

              将检查每一列是否包含 Nan。

              【讨论】:

              • 为什么要在任何内置解决方案上使用它?
              【解决方案15】:

              我一直在使用以下内容并将其转换为字符串并检查 nan 值

                 (str(df.at[index, 'column']) == 'nan')
              

              这使我可以检查系列中的特定值,而不仅仅是返回是否包含在系列中的某个位置。

              【讨论】:

              • 使用这个比pandas.isna() 有什么优势吗?
              • 这允许检查单个字段。
              【解决方案16】:

              最好使用:

              df.isna().any().any()
              

              这里是why。所以isna()是用来定义isnull()的,当然两者是一样的。

              这甚至比公认的答案更快,并且涵盖了所有 2D 熊猫数组。

              【讨论】:

                【解决方案17】:
                df.isnull().sum()
                

                这将为您计算 DataFrame 的各个列中存在的所有 NaN 值。

                【讨论】:

                • 不,这会给你一个系列,它将列名映射到它们各自的 NA 值数量。
                • 已更正,我的错:p
                【解决方案18】:

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

                1. 如果您想查看哪些列有空值,哪些没有(只是 True 和 False)

                  df.isnull().any()
                  
                2. 如果您只想查看包含空值的列

                  df.loc[:, df.isnull().any()].columns
                  
                3. 如果您想查看每列中的空值计数

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

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

                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() 呢?
                【解决方案19】:
                import missingno as msno
                msno.matrix(df)  # just to visualize. no missing value.
                

                【讨论】:

                  【解决方案20】:

                  您不仅可以检查是否存在任何“NaN”,还可以使用以下方法获取每列中“NaN”的百分比,

                  df = pd.DataFrame({'col1':[1,2,3,4,5],'col2':[6,np.nan,8,9,10]})  
                  df  
                  
                     col1 col2  
                  0   1   6.0  
                  1   2   NaN  
                  2   3   8.0  
                  3   4   9.0  
                  4   5   10.0  
                  
                  
                  df.isnull().sum()/len(df)  
                  col1    0.0  
                  col2    0.2  
                  dtype: float64
                  

                  【讨论】:

                    【解决方案21】:

                    我们可以通过使用 seaborn 模块heatmap 生成热图来查看数据集中存在的空值

                    import pandas as pd
                    import seaborn as sns
                    dataset=pd.read_csv('train.csv')
                    sns.heatmap(dataset.isnull(),cbar=False)
                    

                    【讨论】:

                      【解决方案22】:

                      为此,我们可以使用声明 df.isna().any() 。这将检查我们所有的列,如果有任何缺失值,则返回True,如果没有缺失值,则返回NaNs,或False

                      【讨论】:

                        【解决方案23】:

                        试试下面的

                        df.isnull().sum()
                        

                        df.isna().values.any()
                        

                        【讨论】:

                          【解决方案24】:

                          另一种方法是dropna 并检查长度是否相等:

                          >>> len(df.dropna()) != len(df)
                          True
                          >>> 
                          

                          【讨论】:

                            【解决方案25】:

                            我建议使用 values 属性,因为对数组的评估要快得多。

                            arr = np.random.randn(100, 100)
                            arr[40, 40] = np.nan
                            df = pd.DataFrame(arr)
                            
                            %timeit np.isnan(df.values).any()  # 7.56 µs
                            %timeit np.isnan(df).any()         # 627 µs
                            %timeit df.isna().any(axis=None)   # 572 µs
                            

                            结果:

                            7.56 µs ± 447 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
                            627 µs ± 40.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
                            572 µs ± 15.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
                            

                            注意:您需要在 Jupyter 笔记本中运行 %timeit 才能工作

                            【讨论】:

                              【解决方案26】:

                              Bar representation for missing values

                              import missingno
                              missingno.bar(df)# will give you exact no of values and values missing
                              

                              【讨论】:

                                猜你喜欢
                                • 2019-10-20
                                • 2013-11-18
                                • 2021-12-24
                                • 2016-04-04
                                • 2017-07-28
                                • 2017-01-10
                                • 2015-03-01
                                相关资源
                                最近更新 更多