Есть ли способ заменить значения None
в Pandas в Python?
Вы можете использовать df.replace('pre', 'post')
и можете заменить одно значение другим, но этого нельзя сделать, если вы хотите заменить на None
значение, которое при попытке получить странный результат.
Итак, вот пример:
df = DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df.replace('-', 0)
который возвращает успешный результат.
Но,
df.replace('-', None)
который возвращает следующий результат:
0
0 - // this isn't replaced
1 3
2 2
3 5
4 1
5 -5
6 -1
7 -1 // this is changed to `-1`...
8 9
Почему возвращается такой странный результат?
Поскольку я хочу залить этот фрейм данных в базу данных MySQL, я не могу поместить NaN
значения ни в один элемент в моем фрейме данных, а вместо этого хочу поместить None
. Конечно, вы можете сначала изменить , '-'
чтобы NaN
затем конвертировать NaN
в None
, но я хочу знать , почему dataframe действует таким ужасным способом.
Протестировано на pandas 0.12.0 dev на Python 2.7 и OS X 10.8. Python - это предустановленная версия для OS X, и для вашей информации я установил pandas с помощью скрипта SciPy Superpack.
write_frame
не разбираетNaN
s наnone
s?InternalError: (1054, u"Unknown column 'nan' in 'field list'")
ошибкой. Я не знаю ни о каких решениях, кроме преобразованияNaN
в методNone
перед выполнениемwrite_frame
.na_values
аргумента. Больше информации в этом ответе.Ответы:
На самом деле в более поздних версиях pandas это даст TypeError:
df.replace('-', None) TypeError: If "to_replace" and "value" are both None then regex must be a mapping
Вы можете сделать это, передав список или словарь:
In [11]: df.replace('-', df.replace(['-'], [None]) # or .replace('-', {0: None}) Out[11]: 0 0 None 1 3 2 2 3 5 4 1 5 -5 6 -1 7 None 8 9
Но я рекомендую использовать NaN, а не None:
In [12]: df.replace('-', np.nan) Out[12]: 0 0 NaN 1 3 2 2 3 5 4 1 5 -5 6 -1 7 NaN 8 9
источник
df.replace(['-'], [None])
, илиdf.replace({'-': None})
, как мне кажется. ИспользованиеNone
в качестве часового также исключает использование его в качестве значения ..df
себе как:df = df.replace({'?': np.nan})
df.replace('-', df.replace(['-'], [None])
выглядит круто , это опечатка?Я предпочитаю использовать решение
replace
с помощьюdict
из-за его простоты и элегантности:df.replace({'-': None})
Вы также можете иметь больше замен:
df.replace({'-': None, 'None': None})
И даже для более крупных замен всегда очевидно и ясно, что заменяется чем - что, на мой взгляд, сложнее для длинных списков.
источник
dict
типа into_replace
приводит к тому, чтоmethod
параметр не оценивается, и, следовательно, поmethod='pad'
умолчанию не имеет вредных последствий.where
вероятно, то, что вы ищете. Такdata=data.where(data=='-', None)
Из документов panda :
источник
Прежде чем продолжить эту публикацию, важно понять разницу между NaN и None . Один тип с плавающей запятой, другой тип объекта. Pandas лучше подходит для работы со скалярными типами, поскольку многие методы для этих типов можно векторизовать. Pandas пытается последовательно обрабатывать None и NaN, но NumPy не может.
Мое предложение ( и предложение Энди ) - придерживаться NaN.
Но чтобы ответить на ваш вопрос ...
pandas> = 0.18: использовать
na_values=['-']
аргумент сread_csv
Если вы загрузили эти данные из CSV / Excel, у меня для вас хорошие новости. Вы можете подавить это в корне во время загрузки данных вместо того, чтобы писать исправление с кодом в качестве следующего шага.
Большинство
pd.read_*
функций (например,read_csv
иread_excel
) принимаютna_values
атрибут.file.csv
A,B -,1 3,- 2,- 5,3 1,-2 -5,4 -1,-1 -,0 9,0
Теперь, чтобы преобразовать
-
символы в NaN, выполнитеimport pandas as pd df = pd.read_csv('file.csv', na_values=['-']) df A B 0 NaN 1.0 1 3.0 NaN 2 2.0 NaN 3 5.0 3.0 4 1.0 -2.0 5 -5.0 4.0 6 -1.0 -1.0 7 NaN 0.0 8 9.0 0.0
И аналогично для других функций / форматов файлов.
PS: В версии 0.24 + вы можете сохранить целочисленный тип, даже если в вашем столбце есть NaN (да, поговорим о том, чтобы съесть торт и съесть его тоже). Вы можете указать
dtype='Int32'
df = pd.read_csv('file.csv', na_values=['-'], dtype='Int32') df A B 0 NaN 1 1 3 NaN 2 2 NaN 3 5 3 4 1 -2 5 -5 4 6 -1 -1 7 NaN 0 8 9 0 df.dtypes A Int32 B Int32 dtype: object
Dtype - это не обычный тип int ... а скорее целочисленный тип, допускающий значение NULL . Есть и другие варианты.
Обработка числовых данных:
pd.to_numeric
сerrors='coerce
Если вы имеете дело с числовыми данными, более быстрым решением является использование
pd.to_numeric
сerrors='coerce'
аргументом, который принуждает недопустимые значения (значения , которые не могут быть Чугунные числовые) NaN.pd.to_numeric(df['A'], errors='coerce') 0 NaN 1 3.0 2 2.0 3 5.0 4 1.0 5 -5.0 6 -1.0 7 NaN 8 9.0 Name: A, dtype: float64
Чтобы сохранить (обнуляемый) целочисленный dtype, используйте
pd.to_numeric(df['A'], errors='coerce').astype('Int32') 0 NaN 1 3 2 2 3 5 4 1 5 -5 6 -1 7 NaN 8 9 Name: A, dtype: Int32
Чтобы привести несколько столбцов, используйте
apply
:df[['A', 'B']].apply(pd.to_numeric, errors='coerce').astype('Int32') A B 0 NaN 1 1 3 NaN 2 2 NaN 3 5 3 4 1 -2 5 -5 4 6 -1 -1 7 NaN 0 8 9 0
... и присвоить результат обратно после.
Более подробную информацию можно найти в этом ответе .
источник
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9]) df = df.where(df!='-', None)
источник
Установка нулевых значений может быть выполнена с помощью
np.nan
:import numpy as np df.replace('-', np.nan)
Преимущество в том, что
df.last_valid_index()
признает их недействительными.источник
Использование replace и назначение нового df:
import pandas as pd df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9]) dfnew = df.replace('-', 0) print(dfnew) (venv) D:\assets>py teste2.py 0 0 0 1 3 2 2 3 5 4 1 5 -5
источник
df.replace('-', np.nan).astype("object")
Это гарантирует, что вы сможете использовать
isnull()
позже в своем фрейме данныхисточник
С версией Pandas ≥1.0.0 я бы использовал
DataFrame.replace
илиSeries.replace
:df.replace(old_val, pd.NA, inplace=True)
Это лучше по двум причинам:
pd.NA
вместоNone
илиnp.nan
.источник