Jak sprawdzić, czy jakakolwiek wartość to NaN w ramce danych Pandas


Odpowiedzi:


577

Odpowiedź jwilnera jest natychmiastowa. Badałem, czy jest szybsza opcja, ponieważ z mojego doświadczenia, sumowanie płaskich tablic jest (dziwnie) szybsze niż liczenie. Ten kod wydaje się szybszy:

df.isnull().values.any()

Na przykład:

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()jest nieco wolniejszy, ale oczywiście ma dodatkowe informacje - liczbę NaNs.


1
Dziękuję za testy porównawcze czasu. Zaskakujące jest to, że pandasnie ma do tego wbudowanej funkcji. To prawda, że ​​post @ JGreenwell df.describe()może to zrobić, ale nie ma bezpośredniej funkcji.
hlin117

2
Właśnie mierzyłem czas df.describe()(bez znalezienia NaNs). W przypadku tablicy 1000 x 1000 pojedyncze połączenie zajmuje 1,15 sekundy.
hlin117

3
: 1, Ponadto df.isnull().values.sum()jest nieco szybszy niżdf.isnull().values.flatten().sum()
Zero

Ach, dobry chwyt @JohnGalt - zmienię moje rozwiązanie, aby usunąć z .flatten()plakatu. Dzięki.
S Anand

6
Nie próbowałeś df.isnull().values.any(), dla mnie jest szybszy niż inni.
CK1,

178

Masz kilka opcji.

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

Teraz ramka danych wygląda mniej więcej tak:

          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
  • Opcja 1 : df.isnull().any().any()- Zwraca wartość logiczną

Wiesz o tym, isnull()która zwróciłaby ramkę danych taką jak ta:

       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

Jeśli to zrobisz df.isnull().any(), możesz znaleźć tylko kolumny, które mają NaNwartości:

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

Jeszcze jeden .any()powie ci, czy którykolwiek z powyższych jestTrue

> df.isnull().any().any()
True
  • Opcja 2 : df.isnull().sum().sum()- Zwraca liczbę całkowitą całkowitej liczby NaNwartości:

Działa to w ten sam sposób, co .any().any()robi, najpierw podając sumę liczby NaNwartości w kolumnie, a następnie sumując te wartości:

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

Wreszcie, aby uzyskać całkowitą liczbę wartości NaN w DataFrame:

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

Dlaczego nie używać .any(axis=None)zamiast .any().any()?
Georgy

57

Aby dowiedzieć się, które wiersze zawierają NaN w określonej kolumnie:

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

17
Aby dowiedzieć się, które wiersze nie mają Nans w kolumnie szczególnych: non_nan_rows = df[df['name column'].notnull()].
Elmex80s

49

Jeśli chcesz wiedzieć, ile wierszy zawiera „jeden lub więcej NaNs”:

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

Lub jeśli musisz wyciągnąć te rzędy i zbadać je:

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

4
Myślę, że nie potrzebujemy drugiego T
YOBEN_S


18

Dodając do płyty genialną odpowiedź, jestem zupełnie nowy w Pythonie i Pandach, więc proszę wskazać, czy się mylę.

Aby dowiedzieć się, które wiersze mają NaN:

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

wykonałby tę samą operację bez potrzeby transponowania, określając oś dowolnej () jako 1, aby sprawdzić, czy w wierszach występuje „prawda”.


Pozbywa się dwóch transpozycji! Uwielbiam twoje zwięzłe any(axis=1)uproszczenie.
płyty grzewcze

12

Super prosta składnia: df.isna().any(axis=None)

Począwszy od wersji 0.23.2 , można użyć DataFrame.isna+, DataFrame.any(axis=None)gdzie axis=Noneokreśla logiczną redukcję w całej ramce danych.

# 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

Przydatne alternatywy

numpy.isnan
Kolejna wydajna opcja, jeśli korzystasz ze starszych wersji pand.

np.isnan(df.values)

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

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

Ewentualnie sprawdź sumę:

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

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

Series.hasnans
Możesz także iteracyjnie zadzwonić Series.hasnans. Na przykład, aby sprawdzić, czy pojedyncza kolumna ma NaN,

df['A'].hasnans
# True

Aby sprawdzić, czy jakakolwiek kolumna ma NaN, możesz skorzystać ze zrozumienia any(co jest operacją zwarcia).

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

To jest naprawdę bardzo szybkie.


10

Ponieważ żaden z nich nie wspomniał, istnieje tylko jedna zmienna o nazwie hasnans .

df[i].hasnanswyświetli się, Truejeśli jedna lub więcej wartości w serii pand to NaN,False jeśli nie. Zauważ, że to nie jest funkcja.

wersja pandy „0.19.2” i „0.20.2”


6
Ta odpowiedź jest niepoprawna. Serie Pandy mają ten atrybut, ale DataFrames nie. Jeśli df = DataFrame([1,None], columns=['foo']), to df.hasnansrzuci AttributeError, ale df.foo.hasnanswróci True.
Nathan Thompson

7

Ponieważ muszę pandassię tego dowiedzieć DataFrame.dropna(), przyjrzałem się, jak to zaimplementowali, i odkryłem, że skorzystali DataFrame.count(), co zlicza wszystkie wartości inne niż null w DataFrame. Por. kod źródłowy pandy . Nie przeprowadziłem testów porównawczych tej techniki, ale sądzę, że autorzy biblioteki prawdopodobnie dokonali mądrego wyboru.


6

niech dfbędzie nazwą Pandas DataFrame i dowolną wartością, która jest numpy.nanwartością zerową.

  1. Jeśli chcesz zobaczyć, które kolumny mają wartości null, a które nie (tylko prawda i fałsz)
    df.isnull().any()
  2. Jeśli chcesz zobaczyć tylko kolumny z zerami
    df.loc[:, df.isnull().any()].columns
  3. Jeśli chcesz zobaczyć liczbę zer w każdej kolumnie
    df.isna().sum()
  4. Jeśli chcesz zobaczyć procent zerowych wartości w każdej kolumnie

    df.isna().sum()/(len(df))*100
  5. Jeśli chcesz zobaczyć procent zer w kolumnach tylko z zerami: df.loc[:,list(df.loc[:,df.isnull().any()].columns)].isnull().sum()/(len(df))*100

EDYCJA 1:

Jeśli chcesz zobaczyć, gdzie brakuje danych:

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

Jeśli chcesz zobaczyć liczbę zer w każdej kolumnie ... To wydaje się szalone, dlaczego po prostu nie zrobić df.isna().sum()?
AMC

4

Wystarczy użyć math.isnan (x) , Zwróć True, jeśli x jest NaN (nie liczbą), a False inaczej.


4
Nie sądzę, że math.isnan(x)zadziała, gdy xjest ramką DataFrame. Zamiast tego otrzymasz TypeError.
hlin117

Dlaczego miałbyś używać tego zamiast jakiejkolwiek alternatywy?
AMC

4
df.isnull().sum()

To da ci zliczenie wszystkich wartości NaN obecnych w odpowiednich kolorach DataFrame.


Nie, to da Ci Serię, która mapuje nazwy kolumn na ich odpowiednią liczbę wartości NA.
AMC

Poprawione, moja wina: p
Adarsh ​​singh

3

Oto kolejny interesujący sposób znalezienia wartości null i zastąpienia jej wartością obliczoną

    #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

3

Korzystałem z następujących i wpisz rzut casting na ciąg i sprawdzanie wartości nan

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

To pozwala mi sprawdzić określoną wartość w serii, a nie tylko zwrócić, jeśli jest ona zawarta gdzieś w serii.


Czy jest z tego korzyść pandas.isna()?
AMC

2

Najlepiej byłoby użyć:

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

Oto dlaczego . isna()Służy więc do definiowania isnull(), ale oba są oczywiście identyczne.

Jest to nawet szybsze niż zaakceptowana odpowiedź i obejmuje wszystkie tablice panda 2D.


1

Lub możesz użyć .info()na DFtakich jak:

df.info(null_counts=True) która zwraca liczbę niepustych wierszy w kolumnach takich jak:

<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


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

Sprawdza dla każdej kolumny, czy zawiera Nan, czy nie.


Po co używać tego w stosunku do któregokolwiek z wbudowanych rozwiązań?
AMC

0

Widzimy prezent wartości null w zbiorze danych poprzez generowanie mapę cieplną przy użyciu modułu Seaborn mapę cieplną

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

-1

Możesz nie tylko sprawdzić, czy istnieje jakikolwiek „NaN”, ale także uzyskać procent „NaN” w każdej kolumnie, stosując następujące informacje,

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

-2

W zależności od rodzaju danych, z którymi masz do czynienia, możesz również uzyskać zliczenia wartości każdej kolumny podczas wykonywania EDA, ustawiając dropna na False.

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

Działa dobrze dla zmiennych jakościowych, nie tak bardzo, gdy masz wiele unikalnych wartości.


Myślę, że to jest nieefektywne. Wbudowane funkcje pand są bardziej uporządkowane / zwięzłe. Unika bałaganu w notebooku ipython.
Koo,

Nie ma sensu używać tego w porównaniu z wbudowanymi rozwiązaniami.
AMC
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.