Яка різниця між NaN та None?


94

Я читаю два стовпці CSV-файлу за допомогою панд, readcsv()а потім присвоюю значення словнику. Стовпці містять рядки цифр і букв. Іноді бувають випадки, коли клітина порожня. На мою думку, значення, прочитане для цього словникового запису, має бути, Noneале замість цього nanприсвоюється. Звичайно, Noneце є більш описовим для порожньої комірки, оскільки воно має нульове значення, тоді як nanпросто говорить, що прочитане значення не є числом.

Чи правильно я розумію, в чому різниця між Noneі nan? Чому nanпризначається замість None?

Крім того, моя перевірка словника на наявність порожніх комірок використовувала numpy.isnan():

for k, v in my_dict.iteritems():
    if np.isnan(v):

Але це призводить до помилки, оскільки я не можу використовувати цю перевірку для v. Я думаю, це тому, що ціла чи плаваюча змінна, а не рядок, призначена для використання. Якщо це правда, як я можу перевірити vнаявність «порожньої комірки» / nanсправи?


Текст qwertyне є числом.
Роберт Харві,

1
@RobertHarvey Я знаю, тому, безсумнівно, Noneбув би кращий опис значення порожньої клітинки.
user1083734

Відповіді:


107

NaN використовується в якості заповнювача для відсутніх даних послідовно в панді , консистенція хороша. Я зазвичай читаю / перекладаю NaN як "відсутній" . Також див. Розділ "Робота з відсутніми даними" у документах.

Уес пише в документах "вибір NA-представлення" :

Після багатьох років виробничого використання [NaN] виявилося, принаймні на мій погляд, найкращим рішенням з огляду на стан справ у NumPy та Python загалом. Спеціальне значення NaN (Not-A-Number) використовується всюди в якості значення NA, і є функції API , isnullі notnullякі можуть бути використані через dtypes для виявлення значення NA.
...
Таким чином, я вибрав пітонічний підхід "практичність перевершує чистоту" і обміняв цілочисельну здатність NA для набагато простішого підходу до використання спеціального значення в масивах float та object для позначення NA та просування цілочисельних масивів до плаваючих, коли NA повинні бути введено.

Примітка: "gotcha", що цілі ряди, що містять відсутні дані, оновляються до плаваючих .

На мій погляд, головною причиною використання NaN (над None) є те, що його можна зберігати з використанням типу numpy float64 dtype, а не менш ефективним об'єктом dtype, див. Акції типу NA .

#  without forcing dtype it changes None to NaN!
s_bad = pd.Series([1, None], dtype=object)
s_good = pd.Series([1, np.nan])

In [13]: s_bad.dtype
Out[13]: dtype('O')

In [14]: s_good.dtype
Out[14]: dtype('float64')

Джефф коментує (нижче) це:

np.nanдозволяє векторизовані операції; це плаваюче значення, тоді як None, за визначенням, змушує тип об'єкта, що в основному відключає всю ефективність в numpy.

Тож повторіть 3 рази швидко: object == bad, float == good

Говорячи про це, багато операцій все ще можуть працювати так само добре з None проти NaN (але, можливо, не підтримуються, тобто іноді можуть давати дивовижні результати ):

In [15]: s_bad.sum()
Out[15]: 1

In [16]: s_good.sum()
Out[16]: 1.0

Щоб відповісти на друге запитання:
Ви повинні використовувати pd.isnullі pd.notnullперевірити відсутність даних (NaN).


19
просто додавання 2c сюди .... np.nanдозволяє векторизовані операції; це плаваюче значення, в той час як Noneза визначенням примушує objectтип, і в основному відключає всю ефективність в numpy, тому повторіть 3 рази швидко:object==bad, float==good
Джефф

1
Є <NA>також np.nan?
Gathide

18

NaNможе використовуватися як числове значення для математичних операцій, тоді як Noneне може (або, принаймні, не повинно).

NaNє числовим значенням, як визначено у стандарті з плаваючою точкою IEEE 754 . Noneє внутрішнім типом Python ( NoneType) і в цьому контексті буде більше схожим на "неіснуючий" або "порожній", ніж "числово недійсний".

Головний "симптом" цього полягає в тому, що, якщо ви виконаєте, скажімо, середнє значення або суму в масиві, що містить NaN, навіть один, в результаті ви отримаєте NaN ...

З іншого боку, ви не можете виконувати математичні операції, використовуючи Noneяк операнд.

Отже, залежно від випадку, ви можете використовувати Noneяк спосіб сказати своєму алгоритму не враховувати недійсні або неіснуючі значення при обчисленнях. Це означало б, що алгоритм повинен перевірити кожне значення, щоб перевірити, чи воно є None.

Numpy має деякі функції, щоб уникнути значень NaN для забруднення ваших результатів, таких як nansumі, nan_to_numнаприклад.


Я погоджуюсь з вами, що None не слід використовувати для неіснуючих записів, то чому ж df=pd.readcsv('file.csv')мені дають NaNзначення для порожніх комірок, а ні None? Наскільки мені відомо, pd.DataFrames не є ексклюзивними для номерів.
user1083734

Ну, це, мабуть, вибір дизайну. Я припускаю, що DataFrames та Series мають a dtype, тому недійсні значення of dtype=floatповинні бути представлені числовими значеннями, що NaNє і Noneнемає ( Noneє NoneType).
heltonbiker

Крім того, у багатьох методів Pandas є naаргумент, який дозволяє вирішити, яке значення ви збираєтеся використовувати для заміни недоступних значень
heltonbiker

Добре, дякую. Отже, я фактично не читаю цифри у своєму DataFrame, а рядки цифр та букв. Яку перевірку я повинен використовувати для виявлення порожніх комірок? Чек типу; якщо dtype == float: ??
user1083734

Можливо, розміщення зразка ваших даних CSV допомогло б. Я можу уявити, що якщо є рядки, то dtype буде рядком для цілого стовпця (Серія). Але, можливо, якщо не кожен рядок має однакову кількість стовпців, ви отримаєте недоступні дані. Я думаю, вам доведеться це перевірити.
heltonbiker

3

Функція isnan()перевіряє, чи є щось "Не числом", і повертає, чи є змінна числом, наприклад isnan(2), поверне false

Умовна myVar is not Noneповертає, незалежно від того, визначена змінна

Ваш масив numpy використовує, isnan()оскільки він призначений масивом чисел, і він ініціалізує всі елементи масиву, щоб NaNці елементи вважалися "порожніми"


1
Я думаю, isnan(2)що повернувся б False, оскільки 2 не є NaN.
heltonbiker

Крім того, numpy.emptyне ініціалізує значення масиву в NaN. Це просто не ініціалізує значення взагалі.
heltonbiker

5
Правильна перевірка на None-ness є myVar is not None, ні myVar != None.
Хайме

3
Зверніть увагу, що np.isnan()це не реалізовано для рядкових змінних, тому, якщо ви передасте йому рядок, він вийде з ладу. Краще використовувати те, pd.isnullщо працює зі рядками.
Майкл

-1

Нижче наводяться відмінності:

  • nan належить до класу float
  • None належить до класу NoneType

Я знайшов нижченаведену статтю дуже корисною: https://medium.com/analytics-vidhya/dealing-with-missing-values-nan-and-none-in-python-6fc9b8fb4f31


Хоча це посилання може відповісти на питання, краще включити сюди основні частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
А. Коотстра,

@ A.Kootstra Я розумію
eswara amirthan s

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