У вас є три основні варіанти перетворення типів у пандах:
to_numeric()
- забезпечує функціональність для безпечного перетворення нечислових типів (наприклад, рядків) у відповідний числовий тип. (Див. Також to_datetime()
і to_timedelta()
.)
astype()
- перетворити (майже) будь-який тип у (майже) будь-який інший тип (навіть якщо це не обов'язково розумно робити). Також дозволяє перетворити на категоріальні типи (дуже корисно).
infer_objects()
- корисний метод для перетворення стовпців об'єктів, що містять об’єкти Python, у тип панди, якщо це можливо.
Читайте далі для більш детальних пояснень та використання кожного з цих методів.
1. to_numeric()
Найкращий спосіб конвертувати один або кілька стовпців DataFrame в числові значення - це використовувати pandas.to_numeric()
.
Ця функція спробує змінити нечислові об'єкти (наприклад, рядки) на цілі числа чи числа з плаваючою точкою, якщо це доречно.
Основне використання
Вхідним 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
що має тип об'єкта:
>>> 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()
дасть вам або a, int64
або float64
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
Downcasting на "float" аналогічно вибирає менший, ніж звичайний, плаваючий тип:
>>> pd.to_numeric(s, downcast='float')
0 1.0
1 2.0
2 -7.0
dtype: float32
2. astype()
astype()
Метод дозволяє бути чітко про DTYPE ви хочете , щоб ваш DataFrame або серії , щоб мати. Це дуже універсально, тому що ви можете спробувати перейти від одного типу до іншого.
Основне використання
Просто виберіть тип: ви можете використовувати тип NumPy (наприклад np.int16
), деякі типи Python (наприклад, bool) або типи, пов’язані з пандами (наприклад, категоричний тип).
Викличте метод на об'єкті, який ви хочете перетворити, і 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
значення, ви отримаєте помилку при спробі перетворити його в ціле число.
Що стосується панд 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 панд введено метод infer_objects()
перетворення стовпців 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)
натомість.