Заміна Pandas або Numpy Nan на None для використання з MysqlDB


127

Я намагаюся написати кадр даних Pandas (або можна використовувати масив numpy) до бази даних mysql за допомогою MysqlDB. MysqlDB, схоже, не розуміє "nan", і моя база даних видаляє помилку, кажучи, що nan не знаходиться в списку полів. Мені потрібно знайти спосіб перетворити 'nan' в NoneType.

Будь-які ідеї?


2
Чи немає настройки можна змінити в панд , щоб зробити його повернутися Noneна NULLзамість nan?
Натан Хінчі

Відповіді:


194

@bogatron має право, ви можете скористатися where, варто зазначити, що ви можете це робити в пандах:

df1 = df.where(pd.notnull(df), None)

Примітка: це змінює тип всіх стовпців на object.

Приклад:

In [1]: df = pd.DataFrame([1, np.nan])

In [2]: df
Out[2]: 
    0
0   1
1 NaN

In [3]: df1 = df.where(pd.notnull(df), None)

In [4]: df1
Out[4]: 
      0
0     1
1  None

Примітка: те, що ви не можете зробити переробити DataFrames, dtypeщоб дозволити всі типи даних, використовуючи astype, а потім fillnaметод DataFrame :

df1 = df.astype(object).replace(np.nan, 'None')

На жаль, ні це, ні використання не replaceпрацює з Noneдив. Цю (закриту) проблему .


В сторону варто зазначити, що для більшості випадків використання вам не потрібно замінювати NaN на None, дивіться це питання про різницю між NaN та None у пандах .

Однак у цьому конкретному випадку вам здається, що ви робите (принаймні на час відповіді).


дивись документи pandas.pydata.org/pandas-docs/stable/…
Jeff

1
FWIW .. це також змінить тип стовпців на заперечення, вам, мабуть, все одно
Джефф

@Jeff Дякую за посилання, дивно, я не міг його знайти раніше! Я подумав, що треба змінити тип, щоб дозволити None, безумовно, варто згадати!
Енді Хайден

корисно використовувати перед вставкою з Django, щоб уникнути np.nanперетворення на рядок"nan"
shadi

Корисний застереження. Має сенс перебрати тільки ті стовпці, які вже dtypeвід objectі роблять це для тих , хто і обробляти інші типи по- різному , як це необхідно. В ідеалі, це fillna(None)було б приголомшливо.
Вішал


17

Ви можете замінити nanз Noneвашої Numpy масиву:

>>> x = np.array([1, np.nan, 3])
>>> y = np.where(np.isnan(x), None, x)
>>> print y
[1.0 None 3.0]
>>> print type(y[1])
<type 'NoneType'>

2
Єдине потенційне занепокоєння - це зміна dtype, x.dtypeє dtype('float64'), поки y.dtypeє dtype('object').
Хайме


4

Просто доповнення до відповіді @Andy Hayden:

Оскільки DataFrame.maskце протилежний близнюк DataFrame.where, вони мають точно такий же підпис, але з протилежним значенням:

  • DataFrame.whereкорисно для Замінюючи значення , де умова Хибне .
  • DataFrame.mask використовується для заміни значень, де умовою є True .

Тож у цьому питанні використання df.mask(df.isna(), other=None, inplace=True)може бути більш інтуїтивно зрозумілим.


2

Ще одне доповнення: будьте обережні, замінюючи кратні і перетворюючи тип стовпця назад з об'єкта в плаваючий . Якщо ви хочете бути впевнені, що ваш Noneне повернеться назад np.NaN, застосуйте пропозицію @ andy-hayden із використанням pd.where. Ілюстрація того, як заміна все ще може піти не так:

In [1]: import pandas as pd

In [2]: import numpy as np

In [3]: df = pd.DataFrame({"a": [1, np.NAN, np.inf]})

In [4]: df
Out[4]:
     a
0  1.0
1  NaN
2  inf

In [5]: df.replace({np.NAN: None})
Out[5]:
      a
0     1
1  None
2   inf

In [6]: df.replace({np.NAN: None, np.inf: None})
Out[6]:
     a
0  1.0
1  NaN
2  NaN

In [7]: df.where((pd.notnull(df)), None).replace({np.inf: None})
Out[7]:
     a
0  1.0
1  NaN
2  NaN

Дякуємо, що додали це. Переглянувши документацію ще раз, я досі не можу зрозуміти цю поведінку. У будь-якому випадку, це можна вирішити, .replace({np.nan: None})
зачепивши

1
Так, ви можете закінчити, додавши ще один replace({np.nan: None}). Мій коментар був доданий, щоб вказати на потенційну камену під час заміни np.nan. Сказане, безумовно, спонукало мене трохи!
gaatjeniksaan

1

Досить старий, але я натрапив на те саме питання. Спробуйте зробити це:

df['col_replaced'] = df['col_with_npnans'].apply(lambda x: None if np.isnan(x) else x)

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