So überprüfen Sie, ob in einem Pandas DataFrame ein Wert NaN ist

483

Wie kann in Python Pandas am besten überprüft werden, ob ein DataFrame einen (oder mehrere) NaN-Werte hat?

Ich kenne die Funktion pd.isnan, aber dies gibt einen DataFrame von Booleschen Werten für jedes Element zurück. Dieser Beitrag hier beantwortet auch meine Frage nicht genau.

hlin117
quelle
2
Check out Zusammenfassung der
Anzahl

Antworten:

577

Die Antwort von jwilner ist genau richtig . Ich habe untersucht, ob es eine schnellere Option gibt, da das Summieren von flachen Arrays meiner Erfahrung nach (seltsamerweise) schneller ist als das Zählen. Dieser Code scheint schneller zu sein:

df.isnull().values.any()

Zum Beispiel:

In [2]: df = pd.DataFrame(np.random.randn(1000,1000))

In [3]: df[df > 0.9] = pd.np.nan

In [4]: %timeit df.isnull().any().any()
100 loops, best of 3: 14.7 ms per loop

In [5]: %timeit df.isnull().values.sum()
100 loops, best of 3: 2.15 ms per loop

In [6]: %timeit df.isnull().sum().sum()
100 loops, best of 3: 18 ms per loop

In [7]: %timeit df.isnull().values.any()
1000 loops, best of 3: 948 µs per loop

df.isnull().sum().sum()ist etwas langsamer, hat aber natürlich zusätzliche Informationen - die Anzahl der NaNs.

S Anand
quelle
1
Vielen Dank für die Zeitbenchmarks. Es ist überraschend, dass pandashierfür keine Funktion eingebaut ist. Es ist wahr, dass @ JGreenwells Post dies df.describe()kann, aber keine direkte Funktion.
hlin117
2
Ich habe gerade eine Zeitmessung durchgeführt df.describe()(ohne NaNs zu finden). Bei einem 1000 x 1000-Array dauert ein einzelner Anruf 1,15 Sekunden.
hlin117
3
: 1, df.isnull().values.sum()ist auch etwas schneller alsdf.isnull().values.flatten().sum()
Zero
Ah, guter Fang @JohnGalt - Ich werde meine Lösung ändern, um die .flatten()für das Posting zu entfernen . Vielen Dank.
S Anand
6
Du hast es nicht versucht df.isnull().values.any(), für mich ist es schneller als die anderen.
CK1
178

Sie haben mehrere Möglichkeiten.

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

Jetzt sieht der Datenrahmen ungefähr so ​​aus:

          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
  • Option 1 : df.isnull().any().any()- Dies gibt einen booleschen Wert zurück

Sie wissen, isnull()welche einen Datenrahmen wie diesen zurückgeben würden:

       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

Wenn Sie es schaffen df.isnull().any(), können Sie nur die Spalten finden, die NaNWerte haben:

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

Einer noch .any() wird Ihnen sagen, ob eine der oben genanntenTrue

> df.isnull().any().any()
True
  • Option 2 : df.isnull().sum().sum()- Dies gibt eine Ganzzahl der Gesamtzahl der NaNWerte zurück:

Dies funktioniert genauso wie das .any().any() , indem zuerst eine Summe der Anzahl der NaNWerte in einer Spalte und dann die Summe dieser Werte angegeben wird:

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

Um die Gesamtzahl der NaN-Werte im DataFrame abzurufen:

df.isnull().sum().sum()
5
Andy
quelle
Warum nicht .any(axis=None)statt verwenden .any().any()?
Georgy
57

So finden Sie heraus, welche Zeilen NaNs in einer bestimmten Spalte enthalten:

nan_rows = df[df['name column'].isnull()]
Ihor Ivasiuk
quelle
17
So finden Sie heraus, welche Zeilen in einer bestimmten Spalte keine NaNs enthalten : non_nan_rows = df[df['name column'].notnull()].
Elmex80s
49

Wenn Sie wissen müssen, wie viele Zeilen es mit "einem oder mehreren NaNs" gibt:

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

Oder wenn Sie diese Zeilen herausziehen und untersuchen müssen:

nan_rows = df[df.isnull().T.any().T]
Kochfelder
quelle
4
Ich denke, wir brauchen den 2. T
YOBEN_S
38

df.isnull().any().any() Sollte es tun.

jwilner
quelle
18

Ich bin sehr neu in Python und Pandas. Bitte weisen Sie darauf hin, wenn ich falsch liege.

So finden Sie heraus, welche Zeilen NaNs haben:

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

würde dieselbe Operation ausführen, ohne dass eine Transponierung erforderlich ist, indem die Achse von any () als 1 angegeben wird, um zu überprüfen, ob 'True' in Zeilen vorhanden ist.

Ankit
quelle
Dadurch werden zwei Transponierungen beseitigt! Lieben Sie Ihre prägnante any(axis=1)Vereinfachung.
Kochfelder
12

Super einfache Syntax: df.isna().any(axis=None)

Ab Version 0.23.2 können Sie DataFrame.isna+ verwenden, DataFrame.any(axis=None)wobei axis=Nonedie logische Reduzierung über den gesamten DataFrame festgelegt wird.

# 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

Nützliche Alternativen

numpy.isnan
Eine weitere performante Option, wenn Sie ältere Versionen von Pandas ausführen.

np.isnan(df.values)

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

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

Alternativ können Sie die Summe überprüfen:

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

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

Series.hasnans
Sie können auch iterativ anrufen Series.hasnans. Um beispielsweise zu überprüfen, ob eine einzelne Spalte NaNs enthält,

df['A'].hasnans
# True

Und um zu überprüfen, ob eine Spalte NaNs enthält, können Sie ein Verständnis mit verwenden any(was eine Kurzschlussoperation ist).

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

Das geht eigentlich sehr schnell.

cs95
quelle
10

Da keiner erwähnt hat, gibt es nur eine andere Variable, die aufgerufen wird hasnans.

df[i].hasnanswird ausgegeben, Truewenn einer oder mehrere der Werte in der Pandas-Serie NaN ist, Falsewenn nicht. Beachten Sie, dass es keine Funktion ist.

Pandas Version '0.19.2' und '0.20.2'

Yazhi
quelle
6
Diese Antwort ist falsch. Pandas-Serien haben dieses Attribut, DataFrames jedoch nicht. Wenn df = DataFrame([1,None], columns=['foo']), dann df.hasnanswird ein werfen AttributeError, aber df.foo.hasnanszurückkehren True.
Nathan Thompson
7

Da ich das pandasherausfinden muss DataFrame.dropna(), habe ich mir angesehen, wie sie es implementieren, und festgestellt, dass sie es verwendet haben DataFrame.count(), was alle Nicht-Null-Werte in der zählt DataFrame. Vgl. Pandas Quellcode . Ich habe diese Technik nicht bewertet, aber ich glaube, die Autoren der Bibliothek haben wahrscheinlich eine kluge Entscheidung getroffen, wie sie dies tun soll.

Marshall Hufschmied
quelle
6

Sei dfder Name des Pandas DataFrame und jeder Wert, der numpy.nanein Nullwert ist.

  1. Wenn Sie sehen möchten, welche Spalten Nullen haben und welche nicht (nur Wahr und Falsch)
    df.isnull().any()
  2. Wenn Sie nur die Spalten mit Nullen anzeigen möchten
    df.loc[:, df.isnull().any()].columns
  3. Wenn Sie die Anzahl der Nullen in jeder Spalte anzeigen möchten
    df.isna().sum()
  4. Wenn Sie den Prozentsatz der Nullen in jeder Spalte anzeigen möchten

    df.isna().sum()/(len(df))*100
  5. Wenn Sie den Prozentsatz der Nullen in Spalten nur mit Nullen anzeigen möchten: df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100

EDIT 1:

Wenn Sie sehen möchten, wo Ihre Daten visuell fehlen:

import missingno
missingdata_df = df.columns[df.isnull().any()].tolist()
missingno.matrix(df[missingdata_df])
Naveen Kumar
quelle
Wenn Sie die Anzahl der Nullen in jeder Spalte sehen möchten ... Das scheint verrückt zu sein, warum nicht einfach df.isna().sum()?
AMC
4

Verwenden Sie einfach math.isnan (x) , geben Sie True zurück, wenn x eine NaN (keine Zahl) ist, andernfalls False.

江南 消夏
quelle
4
Ich glaube nicht, dass math.isnan(x)es funktionieren wird, wenn xes sich um einen DataFrame handelt. Sie erhalten stattdessen einen TypeError.
hlin117
Warum sollten Sie dies für eine der Alternativen verwenden?
AMC
4
df.isnull().sum()

Auf diese Weise können Sie alle NaN-Werte zählen, die in den jeweiligen Spalten des DataFrame vorhanden sind.

Adarsh ​​singh
quelle
Nein, das gibt Ihnen eine Reihe, die Spaltennamen ihrer jeweiligen Anzahl von NA-Werten zuordnet.
AMC
Korrigiert, meine Schuld: p
Adarsh ​​singh
3

Hier ist eine weitere interessante Möglichkeit, Null zu finden und durch einen berechneten Wert zu ersetzen

    #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
Jagannath Banerjee
quelle
3

Ich habe Folgendes verwendet und es in einen String umgewandelt und nach dem Nanowert gesucht

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

Auf diese Weise kann ich einen bestimmten Wert in einer Serie überprüfen und nicht nur zurückgeben, wenn dieser irgendwo in der Serie enthalten ist.

Peter Thomas
quelle
Gibt es einen Vorteil gegenüber dieser Verwendung pandas.isna()?
AMC
2

Das Beste wäre zu verwenden:

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

Hier ist warum . Wird isna()also zum Definieren verwendet isnull(), aber beide sind natürlich identisch.

Dies ist sogar schneller als die akzeptierte Antwort und deckt alle 2D-Panda-Arrays ab.

Prosti
quelle
1

Oder Sie verwenden können , .info()auf dem DFwie zum Beispiel:

df.info(null_counts=True) Dies gibt die Anzahl der nicht leeren Zeilen in einer Spalte zurück, wie z.

<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
Jan Sila
quelle
1
import missingno as msno
msno.matrix(df)  # just to visualize. no missing value.

Geben Sie hier die Bildbeschreibung ein

Ikbel Benabdessamad
quelle
0
df.apply(axis=0, func=lambda x : any(pd.isnull(x)))

Überprüft für jede Spalte, ob sie Nan enthält oder nicht.

Alex Dlikman
quelle
Warum sollte dies über eine der integrierten Lösungen verwendet werden?
AMC
0

Wir können die Nullwerte in dem Datensatz sehen durch Heatmap mit Seaborn Erzeugungsmodul Heatmap

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

Sie können nicht nur überprüfen, ob 'NaN' vorhanden ist, sondern auch den Prozentsatz der 'NaN' in jeder Spalte mithilfe der folgenden Angaben ermitteln:

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
Nizam
quelle
-2

Abhängig von der Art der Daten, mit denen Sie sich befassen, können Sie bei der Durchführung Ihrer EDA auch einfach die Wertanzahl jeder Spalte abrufen, indem Sie dropna auf False setzen.

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

Funktioniert gut für kategoriale Variablen, nicht so sehr, wenn Sie viele eindeutige Werte haben.

andrewwowens
quelle
Ich halte das für ineffizient. Eingebaute Funktionen von Pandas sind ordentlicher / knapper. Vermeidet Unordnung im Ipython-Notebook.
Koo
Es macht keinen Sinn, dies gegenüber den integrierten Lösungen zu verwenden.
AMC