У вас есть четыре основных варианта преобразования типов в пандах:
to_numeric()
- предоставляет функциональные возможности для безопасного преобразования нечисловых типов. (например, строки) в подходящий числовой тип. (См. Также to_datetime()
и to_timedelta()
.)
astype()
- преобразовать (почти) любой тип в (почти) любого другого типа (даже если это не обязательно разумно). Также позволяет преобразовывать в категориальные типы (очень полезно).
infer_objects()
- служебный метод для преобразования столбцов объекта если возможно, привязать объекты Python к типу pandas.
convert_dtypes()
- преобразовать столбцы DataFrame в наилучший из возможных dtype, который поддерживает pd.NA
(объект pandas для указания отсутствующего значения).
Читайте дальше, чтобы получить более подробные объяснения и использование каждого из этих методов.
1. to_numeric()
Лучший способ преобразовать один или несколько столбцов DataFrame в числовые значения - использовать _ 9_.
Эта функция будет пытаться преобразовать нечисловые объекты (например, строки) в целые числа или числа с плавающей запятой в зависимости от ситуации.
Основное использование
Входными данными для to_numeric()
является серия или один столбец DataFrame.
>>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
>>> s
0 8
1 6
2 7.5
3 3
4 0.9
dtype: object
>>> pd.to_numeric(s) # convert everything to float values
0 8.0
1 6.0
2 7.5
3 3.0
4 0.9
dtype: float64
Как видите, возвращается новая серия. Не забудьте присвоить этот вывод имени переменной или столбца, чтобы продолжить его использование:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
Вы также можете использовать его для преобразования нескольких столбцов DataFrame с помощью метода apply()
:
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Если все ваши значения могут быть преобразованы, это, вероятно, все, что вам нужно.
Обработка ошибок
Но что, если некоторые значения нельзя преобразовать в числовой тип?
to_numeric()
также принимает аргумент ключевого слова errors
, который позволяет принудительно установить нечисловые значения в NaN
или просто игнорировать столбцы, содержащие эти значения.
Вот пример, использующий серию строк s
, которая имеет объект dtype:
>>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
Поведение по умолчанию - поднять, если не удается преобразовать значение. В этом случае он не справляется со строкой pandas:
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
ValueError: Unable to parse string
Вместо того, чтобы потерпеть неудачу, мы могли бы захотеть, чтобы «панды» считались отсутствующим / неверным числовым значением. Мы можем привести недопустимые значения к NaN
следующим образом, используя аргумент ключевого слова errors
:
>>> pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
Третий вариант для errors
- просто игнорировать операцию, если обнаружено недопустимое значение:
>>> pd.to_numeric(s, errors='ignore')
# the original Series is returned untouched
Этот последний вариант особенно полезен, если вы хотите преобразовать весь DataFrame, но не знаете, какие из наших столбцов можно надежно преобразовать в числовой тип. В таком случае просто напишите:
df.apply(pd.to_numeric, errors='ignore')
Функция будет применена к каждому столбцу DataFrame. Столбцы, которые можно преобразовать в числовой тип, будут преобразованы, в то время как столбцы, которые не могут (например, они содержат нецифровые строки или даты), останутся без изменений.
Понижение
По умолчанию преобразование с to_numeric()
даст вам либо int64
, либо float64
dtype (или любую другую целочисленную ширину, присущую вашей платформе).
Обычно это то, что вам нужно, но что, если вы хотите сэкономить немного памяти и использовать более компактный dtype, например float32
или int8
?
to_numeric()
дает вам возможность понижать до «целого», «подписанного», «беззнакового», «плавающего». Вот пример простой серии s
целочисленного типа:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
При понижении до "целого числа" используется наименьшее возможное целое число, которое может содержать значения:
>>> pd.to_numeric(s, downcast='integer')
0 1
1 2
2 -7
dtype: int8
При понижении до 'float' подобным образом выбирается плавающий тип меньшего размера, чем обычно:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2. astype()
Метод astype()
позволяет четко указать dtype, который должен иметь ваш DataFrame или Series. Он очень универсален, так как вы можете пробовать переходить от одного типа к другому.
Основное использование
Просто выберите тип: вы можете использовать dtype NumPy (например, np.int16
), некоторые типы Python (например, bool) или типы, специфичные для pandas (например, категориальный dtype).
Вызовите метод объекта, который хотите преобразовать, и astype()
попытается преобразовать его за вас:
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype('category')
Обратите внимание, я сказал «попробуйте» - если astype()
не знает, как преобразовать значение в Series или DataFrame, это вызовет ошибку. Например, если у вас есть значение NaN
или inf
, вы получите сообщение об ошибке при попытке преобразовать его в целое число.
Начиная с pandas 0.20.0, эту ошибку можно подавить, передав errors='ignore'
. Ваш оригинальный объект будет возвращен нетронутым.
Будь осторожен
astype()
- мощный инструмент, но иногда он может неправильно преобразовывать значения. Например:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Это небольшие целые числа, как насчет преобразования в 8-битный тип без знака для экономии памяти?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
Преобразование сработало, но -7 было преобразовано в 249 (т.е. 2 8 - 7)!
Попытка понизить значение с помощью pd.to_numeric(s, downcast='unsigned')
вместо этого может помочь предотвратить эту ошибку.
3. infer_objects()
Версия 0.21.0 pandas представила метод _51 _ для преобразования столбцов DataFrame, имеющих тип данных объекта, в более конкретный тип (мягкие преобразования).
Например, вот DataFrame с двумя столбцами объектного типа. Один содержит фактические целые числа, а другой - строки, представляющие целые числа:
>>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
>>> df.dtypes
a object
b object
dtype: object
Используя infer_objects()
, вы можете изменить тип столбца 'a' на int64:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
Столбец «b» был оставлен в покое, поскольку его значения были строками, а не целыми числами. Если вы хотите попробовать принудительно преобразовать оба столбца в целочисленный тип, вы можете вместо этого использовать df.astype(int)
.
4. convert_dtypes()
Версия 1.0 и выше включает метод convert_dtypes()
для преобразования столбцов Series и DataFrame в наилучший из возможных dtype, поддерживающий pd.NA
отсутствующее значение.
Здесь лучший из возможных означает тип, наиболее подходящий для хранения значений. Например, это целочисленный тип pandas, если все значения являются целыми числами (или пропущенными значениями): столбец объекта целочисленных объектов Python преобразуется в Int64
, столбец значений NumPy int32
станет pandas dtype Int32
.
С нашим object
DataFrame df
мы получаем следующий результат:
>>> df.convert_dtypes().dtypes
a Int64
b string
dtype: object
Поскольку столбец «a» содержал целочисленные значения, он был преобразован в тип Int64
(который может содержать отсутствующие значения, в отличие от int64
).
Столбец 'b' содержал строковые объекты, поэтому был изменен на pandas 'string
dtype.
По умолчанию этот метод определяет тип на основе значений объекта в каждом столбце. Мы можем изменить это, передав infer_objects=False
:
>>> df.convert_dtypes(infer_objects=False).dtypes
a object
b string
dtype: object
Теперь столбец 'a' остался столбцом объекта: pandas знает, что его можно описать как столбец 'integer' (внутри он работал _ 70_), но не понял, какой именно тип целого числа должен иметь, поэтому не преобразовал его. Столбец «b» снова был преобразован в «строковый» dtype, поскольку он был распознан как содержащий «строковые» значения.
person
Alex Riley
schedule
21.02.2015