pandas arrays, scalars, and data types#
For most data types, pandas uses NumPy arrays as the concrete objects contained with a Index , Series , or DataFrame .
For some data types, pandas extends NumPy’s type system. String aliases for these types can be found at dtypes .
pandas and third-party libraries can extend NumPy’s type system (see Extension types ). The top-level array() method can be used to create a new array, which may be stored in a Series , Index , or as a column in a DataFrame .
PyArrow#
This feature is experimental, and the API can change in a future release without warning.
The arrays.ArrowExtensionArray is backed by a pyarrow.ChunkedArray with a pyarrow.DataType instead of a NumPy array and data type. The .dtype of a arrays.ArrowExtensionArray is an ArrowDtype .
Pyarrow provides similar array and data type support as NumPy including first-class nullability support for all data types, immutability and more.
The table below shows the equivalent pyarrow-backed ( pa ), pandas extension, and numpy ( np ) types that are recognized by pandas. Pyarrow-backed types below need to be passed into ArrowDtype to be recognized by pandas e.g. pd.ArrowDtype(pa.bool_())
Pyarrow-backed string support is provided by both pd.StringDtype(«pyarrow») and pd.ArrowDtype(pa.string()) . pd.StringDtype(«pyarrow») is described below in the string section and will be returned if the string alias «string[pyarrow]» is specified. pd.ArrowDtype(pa.string()) generally has better interoperability with ArrowDtype of different types.
While individual values in an arrays.ArrowExtensionArray are stored as a PyArrow objects, scalars are returned as Python scalars corresponding to the data type, e.g. a PyArrow int64 will be returned as Python int, or NA for missing values.
Pandas ExtensionArray backed by a PyArrow ChunkedArray.
An ExtensionDtype for PyArrow data types.
For more information, please see the PyArrow user guide
Datetimes#
NumPy cannot natively represent timezone-aware datetimes. pandas supports this with the arrays.DatetimeArray extension array, which can hold timezone-naive or timezone-aware values.
Timestamp , a subclass of datetime.datetime , is pandas’ scalar type for timezone-naive or timezone-aware datetime data. NaT is the missing value for datetime data.
Pandas replacement for python datetime.datetime object.
(N)ot-(A)-(T)ime, the time equivalent of NaN.
Properties#
Return numpy datetime64 format in nanoseconds.
Return the day of the year.
Return the day of the year.
Return the number of days in the month.
Return the number of days in the month.
Return True if year is a leap year.
Check if the date is the last day of the month.
Check if the date is the first day of the month.
Check if date is last day of the quarter.
Check if the date is the first day of the quarter.
Return True if date is last day of the year.
Return True if date is first day of the year.
Обзор типов данных Pandas¶
В процессе анализа данных важно убедиться, что вы используете правильные типы данных; в противном случае можете получить неожиданные результаты или ошибки. В этой статье будут обсуждаться основные типы данных pandas (также известные как dtypes ), их сопоставление с типами данных Python и NumPy, а также варианты преобразования.
Типы данных Pandas¶
Тип данных — это, по сути, внутреннее представление, которое язык программирования использует для понимания того, как данные хранить и как ими оперировать. Например, программа должна понимать, что вы хотите сложить два числа, например 5 + 10 , чтобы получить 15 . Или, если у вас есть две строки, такие как «кошка» и «шляпа» вы можете объединить (сложить) их вместе, чтобы получить «кошкашляпа» .
Проблема с типами данных pandas заключается в том, что между pandas, Python и NumPy существует некоторое совпадение.
В следующей таблице приведены основные ключевые моменты:
Pandas | Python | NumPy | Использование |
---|---|---|---|
object | str или смесь | string, unicode, смешанные типы | Текстовые или смешанные числовые и нечисловые значения |
int64 | int | int_, int8, int16, int32, int64, uint8, uint16, uint32, uint64 | Целые числа |
float64 | float | float_, float16, float32, float64 | Числа с плавающей точкой |
bool | bool | bool_ | Значения True/False |
datetime64 | datetime | datetime64[ns] | Значения даты и времени |
timedelta[ns] | NA | NA | Разность между двумя datetimes |
category | NA | NA | Ограниченный список текстовых значений |
В этом Блокноте я сосредоточусь на следующих типах данных pandas:
Про тип category смотрите в отдельной статье.
Тип данных object может фактически содержать несколько разных типов. Например, столбец a может включать целые числа, числа с плавающей точкой и строки, которые вместе помечаются как object . Следовательно, вам могут потребоваться некоторые дополнительные методы для обработки смешанных типов данных.
В этой статье (а тут перевод статьи на русский язык) вы найдете инструкцию по очистке данных, представленных ниже.
Почему нас это волнует?¶
Типы данных — одна из тех вещей, о которых вы, как правило, не заботитесь, пока не получите ошибку или неожиданные результаты. Это также одна из первых вещей, которую вы должны проверить после загрузки новых данных в pandas для дальнейшего анализа.
Я буду использовать очень простой CSV файл, чтобы проиллюстрировать пару распространенных ошибок, которые вы можете встретить.
import pandas as pd import numpy as np
df = pd.read_csv("https://github.com/dm-fedorov/pandas_basic/blob/master/%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B5%20%D0%B2%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%B2%20pandas/data/sales_data_types.csv?raw=True")
Customer Number | Customer Name | 2016 | 2017 | Percent Growth | Jan Units | Month | Day | Year | Active | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 10002.0 | Quest Industries | $125,000.00 | $162500.00 | 30.00% | 500 | 1 | 10 | 2015 | Y |
1 | 552278.0 | Smith Plumbing | $920,000.00 | $101,2000.00 | 10.00% | 700 | 6 | 15 | 2014 | Y |
2 | 23477.0 | ACME Industrial | $50,000.00 | $62500.00 | 25.00% | 125 | 3 | 29 | 2016 | Y |
3 | 24900.0 | Brekke LTD | $350,000.00 | $490000.00 | 4.00% | 75 | 10 | 27 | 2015 | Y |
4 | 651029.0 | Harbor Co | $15,000.00 | $12750.00 | -15.00% | Closed | 2 | 2 | 2014 | N |
На первый взгляд данные выглядят нормально, поэтому попробуем выполнить некоторые операции.
Сложим продажи за 2016 и 2017 годы:
0 $125,000.00$162500.00 1 $920,000.00$101,2000.00 2 $50,000.00$62500.00 3 $350,000.00$490000.00 4 $15,000.00$12750.00 dtype: object
Выглядит странно. Мы хотели суммировать значения столбцов, но pandas их объединил, чтобы создать одну длинную строку.
Ключ к разгадке проблемы — это строка, в которой написано dtype: object .
object — это строка в pandas, поэтому он выполняет строковую конкатенацию вместо математического сложения.
Если мы хотим увидеть все типы данных, которые находятся в кадре данных ( DataFrame ), то воспользуемся атрибутом dtypes :
Customer Number float64 Customer Name object 2016 object 2017 object Percent Growth object Jan Units object Month int64 Day int64 Year int64 Active object dtype: object
Кроме того, функция df.info() показывает много полезной информации:
RangeIndex: 5 entries, 0 to 4 Data columns (total 10 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Customer Number 5 non-null float64 1 Customer Name 5 non-null object 2 2016 5 non-null object 3 2017 5 non-null object 4 Percent Growth 5 non-null object 5 Jan Units 5 non-null object 6 Month 5 non-null int64 7 Day 5 non-null int64 8 Year 5 non-null int64 9 Active 5 non-null object dtypes: float64(1), int64(3), object(6) memory usage: 528.0+ bytes
После просмотра автоматически назначаемых типов данных возникает несколько проблем:
- Customer Number (Номер клиента) — float64 , но должен быть int64 .
- Столбцы 2016 и 2017 хранятся как objects , а не числовые значения, такие как float64 или int64 .
- Percent Growth (Единицы процентного роста) и Jan Units также хранятся как objects , а не числовые значения.
- У нас есть столбцы Month , Day и Year , которые нужно преобразовать в datetime64 .
- Столбец Active должен быть логическим ( boolean ).
Без проведения очистки данных будет сложно провести дополнительный анализ.
- Используйте метод astype() , чтобы принудительно задать тип данных.
- Создайте настраиваемую (custom) функцию для преобразования данных.
- Используйте функции to_numeric() или to_datetime() .
Использование функции astype()¶
Самый простой способ преобразовать столбец данных в другой тип — использовать astype() . Например, чтобы преобразовать Customer Number (Номер клиента) в целое число, можем сделать так:
df['Customer Number'].astype('int') # pandas понимает, что в итоге нужен int64
0 10002 1 552278 2 23477 3 24900 4 651029 Name: Customer Number, dtype: int64
Чтобы изменить Customer Number в исходном кадре данных, обязательно присвойте его обратно столбцу, так как функция astype() возвращает копию:
df["Customer Number"] = df['Customer Number'].astype('int') df.dtypes
Customer Number int64 Customer Name object 2016 object 2017 object Percent Growth object Jan Units object Month int64 Day int64 Year int64 Active object dtype: object
А вот новый кадр данных с Customer Number в качестве целого числа:
Customer Number | Customer Name | 2016 | 2017 | Percent Growth | Jan Units | Month | Day | Year | Active | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 10002 | Quest Industries | $125,000.00 | $162500.00 | 30.00% | 500 | 1 | 10 | 2015 | Y |
1 | 552278 | Smith Plumbing | $920,000.00 | $101,2000.00 | 10.00% | 700 | 6 | 15 | 2014 | Y |
2 | 23477 | ACME Industrial | $50,000.00 | $62500.00 | 25.00% | 125 | 3 | 29 | 2016 | Y |
3 | 24900 | Brekke LTD | $350,000.00 | $490000.00 | 4.00% | 75 | 10 | 27 | 2015 | Y |
4 | 651029 | Harbor Co | $15,000.00 | $12750.00 | -15.00% | Closed | 2 | 2 | 2014 | N |
Все это выглядит хорошо и кажется довольно простым.
Давайте попробуем проделать то же самое со столбцом 2016 и преобразовать его в число с плавающей точкой:
# здесь появится исключение: # df['2016'].astype('float')
Аналогичным образом мы можем попытаться преобразовать столбец Jan Units в целое число:
# здесь тоже появится исключение: # df['Jan Units'].astype('int')
Оба примера возвращают исключения ValueError , т.е. преобразования не сработали.
В каждом из случаев данные включали значения, которые нельзя было интерпретировать как числа. В столбцах продаж данные включают символ валюты $ , а также запятую. В столбце Jan Units последним значением является Closed (Закрыто), которое не является числом; так что мы получаем исключение.
Пока что astype() как инструмент для преобразования выглядит не очень хорошо.
Мы должны попробовать еще раз в столбце Active .
0 True 1 True 2 True 3 True 4 True Name: Active, dtype: bool
На первый взгляд все выглядит нормально, но при ближайшем рассмотрении обнаруживается проблема. Все значения были интерпретированы как True , но последний клиент в столбце Active имеет флаг N вместо Y .
Вывод из этого раздела такой — astype() будет работать, если:
- данные чистые и могут быть просто интерпретированы как число;
- вы хотите преобразовать числовое значение в строковый объект, т.е. вызвать astype(‘str’) .
Если данные содержат нечисловые символы или неоднородны, то astype() будет плохим выбором для преобразования типов. Вам потребуется выполнить дополнительные преобразования, чтобы изменение типа работало правильно.
Дополнительно¶
Отметим, что astype() может принимать словарь имен столбцов и типов данных:
df.astype('Customer Number': 'int', 'Customer Name': 'str'>).dtypes
Customer Number int64 Customer Name object 2016 object 2017 object Percent Growth object Jan Units object Month int64 Day int64 Year int64 Active object dtype: object
Пользовательские функции преобразования¶
Поскольку эти данные немного сложнее преобразовать, можно создать настраиваемую (custom) функцию, которую применим к каждому значению и преобразовать в соответствующий тип данных.
Для конвертации валюты (этого конкретного набора данных) мы можем использовать простую функцию:
def convert_currency(val): """ Преобразует числовое значение строки в число с плавающей точкой: - удаляет $ - удаляет запятые - преобразует в число с плавающей точкой """ new_val = val.replace(',', '').replace('$', '') return float(new_val)
В коде используются строковые функции Python, чтобы очистить символы $ и , , а затем преобразовать значение в число с плавающей точкой. В этом конкретном случае мы могли бы преобразовать значения в целые числа, но я предпочитаю использовать плавающую точку.
Я также подозреваю, что кто-нибудь рекомендует использовать тип данных Decimal для валюты. Это не встроенный тип в pandas, поэтому я намеренно придерживаюсь подхода с плавающей точкой.
Также следует отметить, что функция преобразует число в питоновский float , но pandas внутренне преобразует его в float64 . Как упоминалось ранее, я рекомендую разрешить pandas выполнять такие преобразования. Вам не нужно пытаться понижать до меньшего или повышать до большего размера байта, если вы действительно не знаете, зачем это нужно.
Теперь мы можем использовать функцию apply , чтобы применить ее ко всем значениям в столбце 2016 .