Як перевірити, чи є якесь значення NaN у програмі DataFrame Pandas


483

У Python Pandas, який найкращий спосіб перевірити, чи має DataFrame одне (або більше) значень NaN?

Я знаю про функцію pd.isnan, але це повертає DataFrame булевих символів для кожного елемента. Цей пост прямо тут теж точно не відповідає на моє запитання.


Відповіді:


577

Відповідь jwilner не вказана . Я досліджував, чи є швидший варіант, оскільки, на моєму досвіді, підсумовування плоских масивів (дивним чином) швидше, ніж підрахунок. Цей код здається швидшим:

df.isnull().values.any()

Наприклад:

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()трохи повільніше, але, звичайно, має додаткову інформацію - кількість NaNs.


1
Дякую за орієнтири часу. Дивно, що для pandasцього немає вбудованої функції. Це правда з поста @ JGreenwell, що df.describe()може це зробити, але ніякої прямої функції.
hlin117

2
Я щойно приурочила df.describe()(не знаходячи NaN). З масивом 1000 x 1000 один виклик займає 1,15 секунди.
hlin117

3
: 1, Крім того, df.isnull().values.sum()трохи швидше, ніжdf.isnull().values.flatten().sum()
Нуль

Ах, гарна уловка @JohnGalt - я зміню своє рішення, щоб видалити .flatten()тестування для розміщення. Дякую.
S Anand

6
Ви не пробували df.isnull().values.any(), для мене це швидше, ніж інші.
CK1

178

У вас є пара варіантів.

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
  • Варіант 2 : df.isnull().sum().sum()- Це повертає ціле число від загальної кількості NaNзначень:

Це діє так само, як і дію .any().any(), спочатку даючи підсумок кількості NaNзначень у стовпці, а потім підсумовуючи ці значення:

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

Нарешті, щоб отримати загальну кількість значень NaN у DataFrame:

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

Чому б не використовувати .any(axis=None)замість .any().any()?
Георгій

57

Щоб дізнатися, які рядки мають NaNs у певному стовпці:

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

17
Для того, щоб з'ясувати , які рядки не має пренебрежимо малого в колонці конкретної: non_nan_rows = df[df['name column'].notnull()].
Elmex80s

49

Якщо вам потрібно знати, скільки рядків є з "одним чи кількома NaNs":

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

Або якщо вам потрібно витягнути ці рядки та вивчити їх:

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

4
Я думаю, нам не потрібен 2-й Т
YOBEN_S


18

Додавши Хобсу блискучу відповідь, я дуже новачок у Python and Pandas, тому, будь ласка, вкажіть, чи я помиляюся.

Щоб дізнатися, які рядки мають NaN:

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

буде виконувати ту саму операцію без необхідності переміщення, вказавши вісь будь-якого (), як 1, щоб перевірити, чи в рядках присутній "True".


Це позбавляється від двох транспозитів! Любіть ваше стисле any(axis=1)спрощення.
варильні панелі

12

Супер простий синтаксис: 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
Інший варіант виконання, якщо ви використовуєте старіші версії панд.

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. Наприклад, щоб перевірити, чи є в одному стовпці NaNs,

df['A'].hasnans
# True

І щоб перевірити, чи є якийсь стовпець NaN, ви можете скористатися розумінням any(це операція короткого замикання).

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

Це насправді дуже швидко.


10

Оскільки ніхто не згадував, існує лише інша названа змінна hasnans.

df[i].hasnansвиведе, Trueякщо одне або більше значень у серії панд NaN, Falseякщо ні. Зауважте, що це не функція.

версії панд "0.19.2" та "0.20.2"


6
Ця відповідь невірна. Цей атрибут має серія Pandas, але DataFrames - ні. Якщо df = DataFrame([1,None], columns=['foo']), то df.hasnansкине AttributeError, але df.foo.hasnansповернеться True.
Натан Томпсон

7

Оскільки pandasтреба це з’ясувати DataFrame.dropna(), я переглянув, як вони це реалізують, і виявив, що вони користуються цим DataFrame.count(), який підраховує всі ненульові значення в DataFrame. Ср. вихідний код панди . Я не орієнтувався на цю методику, але вважаю, що автори бібліотеки, ймовірно, зробили мудрий вибір, як це зробити.


6

нехай 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

EDIT 1:

Якщо ви хочете побачити, де ваші дані відсутні візуально:

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

Якщо ви хочете побачити кількість нулів у кожному стовпчику ... Це здається божевільним, чому б просто не зробити df.isna().sum()?
AMC

4

Просто використовуючи math.isnan (x) , Return True, якщо x - NaN (а не число), і False - інакше.


4
Я не думаю, що math.isnan(x)це буде працювати, коли xце DataFrame. Натомість ви отримуєте TypeError.
hlin117

Чому ви використовуєте це над будь-якою з альтернатив?
AMC

4
df.isnull().sum()

Це дасть вам підрахунок усіх значень NaN, наявних у відповідних колоніях DataFrame.


Ні, це дасть вам серію, яка відображає назви стовпців відповідної кількості значень NA.
AMC

Виправлено, я винен: p
Adarsh ​​singh

3

Ось ще один цікавий спосіб знаходження нуля та заміни на обчислене значення

    #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

Я використовую наступне і вводячи його в рядок і перевіряючи значення nan

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

Це дозволяє мені перевірити конкретне значення в серії, а не просто повернути, якщо воно міститься десь у серії.


Чи є якась перевага використання цього над pandas.isna()?
AMC

2

Найкраще було б використовувати:

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

Ось чому . Так isna()використовується для визначення isnull(), але обидва вони, звичайно, ідентичні.

Це навіть швидше, ніж прийнята відповідь і охоплює всі 2D масиви панд.


1

Або ви можете використовувати .info()на DFтаких , як:

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


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

Перевірятиме кожний стовпець, чи містить він Nan чи ні.


Навіщо використовувати це над будь-яким із вбудованих рішень?
AMC

0

Ми можемо побачити нульові значення, наявні в наборі даних, генеруючи теплову карту за допомогою теплової карти модуля новонароджених

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

-1

Ви можете не тільки перевірити, чи існує якийсь "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

-2

Залежно від типу даних, з якими ви маєте справу, ви також можете отримати підрахунок значень кожного стовпця під час виконання свого EDA, встановивши dropna на False.

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

Добре працює для категоричних змінних, не так багато, коли у вас є багато унікальних значень.


Я думаю, що це неефективно. Вбудовані функції панд більш акуратні / стислі. Уникає захаращення зошита ipython.
Ку

Немає сенсу використовувати це над вбудованими рішеннями.
AMC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.