Библиотека Pandas для Python

Оглавление

Знакомство с пандами

Итак, что такое Pandas - практически говоря? Если коротко, то это основная библиотека анализа данных для Python. Для ученых, студентов и профессиональных разработчиков Pandas является основной причиной для изучения или взаимодействия с Python, в отличие от специфического языка статистики, такого как R, или проприетарного академического пакета, такого как SPSS или Matlab. (Интересный факт - Pandas назван в честь термина Panel Data, и изначально был создан для анализа таблиц финансовых данных). Мне нравится думать, что последняя буква "s" означает Series или Statistics.

Хотя существует множество способов исследовать числовые данные с помощью Python "из коробки", все они будут включать в себя довольно низкопроизводительные результаты с тонной шаблонов. В это трудно поверить, но Pandas часто рекомендуют в качестве следующей остановки для пользователей Excel, которые готовы поднять анализ данных на новый уровень. Почти любая проблема, которую можно решить с помощью программы электронных таблиц, может быть решена в Pandas - без всяких графических излишеств.

Более того, поскольку проблемы можно решать в Pandas с помощью Python, решения уже автоматизированы или могут быть запущены как сервис в облаке. Кроме того, Pandas активно использует Numpy, полагаясь на его низкоуровневые вызовы для получения результатов линейной математики на порядки выше Mag

О данных

В этой заметке мы будем использовать интересный набор данных, чтобы продемонстрировать полезный фрагмент библиотеки Pandas. Этот набор данных особенно интересен, поскольку он является частью примера из реального мира, и мы все можем представить себе людей, выстроившихся в очередь в аэропорту (место, где время от времени все идет не так). Глядя на эти данные, я представляю, как люди, сидящие в неудобных креслах в аэропорту, только что обнаружили, что их багаж пропал - не просто временно, но его нигде нет в системе! Или, что еще лучше, представьте, что трудолюбивый сотрудник TSA случайно разбил драгоценную семейную реликвию.

Поэтому, конечно же, пришло время заполнить еще одну форму. Теперь получение данных из форм - интересный процесс с точки зрения сбора данных, поскольку у нас есть набор данных, которые происходят в определенное время. Это фактически означает, что мы можем интерпретировать записи как временной ряд. Кроме того, поскольку люди предоставляют информацию, мы можем узнать кое-что о группе людей.

Вернемся к нашему примеру: допустим, мы работаем в TSA, и нам поручено получить некоторые сведения о том, когда эти несчастные случаи наиболее вероятны, и дать некоторые рекомендации по улучшению работы службы.

Pandas, к счастью, является универсальным инструментом для изучения и анализа этого набора данных. Не стесняйтесь загрузить файл excel в папку проекта, чтобы начать работу, или выполните команду curl, приведенную ниже. Да, pandas может читать файлы .xls или .xlsx с помощью одного вызова команды pd.read_excel()! На самом деле, новичкам, имеющим опыт работы с файлами .csv или excel, часто полезно подумать о том, как они решали бы проблему в excel, а затем понять, насколько проще это может быть в Pandas.

Итак, без лишних слов, откройте терминал, текстовый редактор или вашу любимую IDE и посмотрите сами, используя руководство, приведенное ниже.

Пример данных:

Взять, к примеру, некоторые претензии, предъявленные TSA в процессе досмотра людей или имущества пассажира в связи с травмой, потерей или повреждением. Информация о претензиях включает номер претензии, дату инцидента, тип претензии, сумму претензии, статус и решение.

Каталог: TSA Claims Data
Скачать наши данные: claims-2014.xls

Настройка

Для начала давайте создадим чистый каталог. Вы можете поместить его куда угодно или создать папку проекта в IDE. Используйте выбранный вами метод установки для получения Pandas: Pip, вероятно, самый простой.

$ mkdir -p ~/Desktop/pandas-tutorial/data && cd ~/Desktop/pandas-tutorial

Установите pandas вместе с xldr для загрузки файлов в формате Excel, matplotlib для построения графиков и Numpy для математических функций высокого уровня.

$ pip3 install matplotlib numpy pandas xldr

Опционально: загрузить данные примера с помощью curl:

$ curl -O https://www.dhs.gov/sites/default/files/publications/claims-2014.xls

Запуск Python:

$ python3
Python 3.7.1 (default, Nov  6 2018, 18:46:03)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

Импортировать пакеты:

>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import pandas as pd

Загрузка данных

Загружать данные в Pandas очень просто. Pandas может точно считывать данные практически из любого распространенного формата, включая JSON, CSV и SQL. Данные загружаются во "флагманскую" структуру данных Pandas - DataFrame.

Это термин, который вы захотите запомнить. Вы будете часто слышать о DataFrames. Если этот термин кажется вам непонятным, подумайте о таблице в базе данных или о листе в Excel. Главное, что здесь больше одного столбца: каждая строка или запись имеет несколько полей, которые последовательны от строки к строке.

Вы можете загрузить примерные данные прямо из Интернета:

>>> df = pd.read_excel(io='https://www.dhs.gov/sites/default/files/publications/claims-2014.xls', index_col='Claim Number')

Менее круто, данные могут быть загружены из файла:

$ curl -O https://www.dhs.gov/sites/default/files/publications/claims-2014.xls

>>> df = pd.read_excel(io='claims-2014.xls', index_col='Claim Number')

Основные операции

Выведите информацию о DataFrame, включая dtype индекса и dtypes столбцов, значения non-null и использование памяти. DataFrame.info() является одним из более полезных и универсальных методов, привязанных к DataFrame (их почти 150!).

>>> df.info()
 'pandas.core.frame.dataframe'="">
Int64Index: 8855 entries, 2013081805991 to 2015012220083
Data columns (total 10 columns):
Date Received    8855 non-null datetime64[ns]
Incident Date    8855 non-null datetime64[ns]
Airport Code     8855 non-null object
Airport Name     8855 non-null object
Airline Name     8855 non-null object
Claim Type       8855 non-null object
Claim Site       8855 non-null object
Item Category    8855 non-null object
Close Amount     8855 non-null object
Disposition      8855 non-null object
dtypes: datetime64[ns](2), object(8)
memory usage: 761.0+ KB

Просмотреть первые n строк:

>>> df.info()
 '="">>> df.head(n=3)  # see also df.tail()
    Claim Number Date Received       Incident Date Airport Code       ...              Claim Site                   Item Category Close Amount      Disposition
0  2013081805991    2014-01-13 2012-12-21 00:00:00          HPN       ...         Checked Baggage  Audio/Video; Jewelry & Watches            0             Deny
1  2014080215586    2014-07-17 2014-06-30 18:38:00          MCO       ...         Checked Baggage                               -            0             Deny
2  2014010710583    2014-01-07 2013-12-27 22:00:00          SJU       ...         Checked Baggage                    Food & Drink           50  Approve in Full

[3 rows x 11 columns]

Перечислите все столбцы в DataFrame:

>>> df.columns
Index(['Claim Number', 'Date Received', 'Incident Date', 'Airport Code',
       'Airport Name', 'Airline Name', 'Claim Type', 'Claim Site',
       'Item Category', 'Close Amount', 'Disposition'],
      dtype='object')

Возвращает один столбец (важно - также называется Series):

>>> df['Claim Type'].head()
0    Personal Injury
1    Property Damage
2    Property Damage
3    Property Damage
4    Property Damage
Name: Claim Type, dtype: object

Надеемся, вы начинаете понимать, что представляют собой данные claims-2014.xls.

Dtype

Типы данных - это фундаментальная концепция, которую необходимо хорошо знать, чтобы избежать разочарований в дальнейшем. Pandas использует номенклатуру Numpy, называя тип данных столбца его dtype. Pandas также пытается вывести dtypes при построении DataFrame (т.е. инициализации).

Чтобы воспользоваться преимуществами повышения производительности, присущими Numpy, нам нужно познакомиться с этими типами и узнать, как они примерно переводятся в типы родного Python.

Смотрите еще раз на df.info() и обратите внимание на dtype assig

>>> df.info()
 'pandas.core.frame.dataframe'="">
RangeIndex: 8855 entries, 0 to 8854
Data columns (total 11 columns):
Date Received    8855 non-null datetime64[ns]
Incident Date    8855 non-null datetime64[ns]
Airport Code     8855 non-null object
Airport Name     8855 non-null object
Airline Name     8855 non-null object
Claim Type       8855 non-null object
Claim Site       8855 non-null object
Item Category    8855 non-null object
Close Amount     8855 non-null object
Disposition      8855 non-null object
dtypes: datetime64[ns](2), object(8)
memory usage: 761.1+ KB

dtypes аналогичны настройкам формата текста/чисел, типичным для большинства приложений электронных таблиц, а Pandas использует dtypes для определения того, какой тип (типы) операций может быть выполнен над данными в конкретном столбце. Например, математические операции можно выполнять только над числовыми типами данных, такими как int64 или float64. Столбцы, содержащие действительные даты и/или значения времени, назначаются

Короче говоря, Pandas пытается сделать вывод dtypes при построении DataFrame. Однако, как и во многих приложениях для анализа данных, этот процесс не всегда идеален.

Важно отметить, что Pandas dtype делает выводы с осторожностью: если серия содержит более одного типа данных, она назначается

Очистка и преобразование данных

Данные почти всегда грязные: они почти всегда содержат некоторые данные с нетипичным форматированием; некоторые артефакты, уникальные для среды их происхождения. Поэтому очистка данных имеет решающее значение для обеспечения достоверности анализа. Работа по очистке данных в Pandas в первую очередь включает в себя выявление и повторную обработку неверно выведенных значений dtypes.

>>> df.dtypes
Date Received    datetime64[ns]
Incident Date    datetime64[ns]
Airport Code             object
Airport Name             object
Airline Name             object
Claim Type               object
Claim Site               object
Item Category            object
Close Amount             object
Disposition              object
dtype: object

Вновь взглянув на dtypes нашего DataFrame, мы видим, что Pandas правильно определил dtypes дату получения и дату инцидента как datetime64 dtypes. Таким образом, атрибуты datetime данных столбца доступны во время операций. Например, для обобщения данных по часам дня, когда произошел каждый инцидент, мы можем сгруппировать и обобщить данные по элементу hour столбца datetime64, чтобы определить, в какие часы дня происходят определенные типы инцидентов.

>>> grp = df.groupby(by=df['Incident Date'].dt.hour)
>>> grp['Item Category'].describe()
              count unique                   top freq
Incident Date
0              3421    146  Baggage/Cases/Purses  489
1                 6      5                 Other    2
2                11      9                     -    2
3                 5      5     Jewelry & Watches    1
4                49     18  Baggage/Cases/Purses    6
5               257     39                     -   33
6               357     54                     -   43
7               343     43              Clothing   41
8               299     47                     -   35
9               305     41                     -   31
10              349     45                 Other   43
11              343     41                     -   45
12              363     51                 Other   41
13              359     55                     -   45
14              386     60  Baggage/Cases/Purses   49
15              376     51                 Other   41
16              351     43  Personal Electronics   35
17              307     52                 Other   34
18              289     43  Baggage/Cases/Purses   37
19              241     46  Baggage/Cases/Purses   26
20              163     31  Baggage/Cases/Purses   23
21              104     32  Baggage/Cases/Purses   20
22              106     33  Baggage/Cases/Purses   19
23               65     25  Baggage/Cases/Purses   14

Это работает совершенно идеально - однако, обратите внимание, что Close Amount была загружена как object. Слова типа "Amount" являются хорошим индикатором того, что столбец содержит числовые значения.

Давайте посмотрим на значения в Close Amount.

>>> df['Close Amount'].head()
0     0
1     0
2    50
3     0
4     0
Name: Close Amount, dtype: object

По-моему, они выглядят как числовые значения. Давайте посмотрим на другой конец

>>> df['Close Amount'].tail()
8850      0
8851    800
8852      0
8853    256
8854      -
Name: Close Amount, dtype: object

Вот виновник: индекс # 8854 является строковым значением.

Если Pandas не может объективно определить, что все значения, содержащиеся в столбце DataFrame, являются одинаковыми числовыми или датой/временем dtype, то по умолчанию используется объект.

К счастью, я знаю по опыту, что формат чисел "Бухгалтерский учет" Excel обычно форматирует 0,00 как тире, -.

Итак, как это исправить? Pandas предоставляет общий метод DataFrame.apply, который можно использовать для применения любой одноаргументной функции к каждому значению одного или нескольких столбцов.

В данном случае мы будем использовать его для одновременного преобразования символа - в значение, которое он представляет в Excel, 0.0, и пересчета исходного объекта всего столбца dtype в его правильный объект dtype float64.

Сначала определим новую функцию для выполнения преобразования:

>>> def dash_to_zero(x):
>>>    if '-' in str(x):
>>>        return float() # 0.0
>>>    else:
>>>        return x  # just return the input value as-is

Затем применим функцию к каждому значению Close Amount:

>>> df['Close Amount'] = df['Close Amount'].apply(dash_to_zero)
>>> df['Close Amount'].dtype
dtype('float64')

Эти два шага также можно объединить в однострочную операцию, используя лямбду Python:

>>> df['Close Amount'].apply(lambda x: 0. if '-' in str(x) else x)

Выполнение базового анализа

После того как вы убедились, что ваш набор данных "чист", вы готовы к анализу данных! Агрегирование - это процесс получения суммарных данных, которые могут быть более полезными, чем те мелкозернистые значения, которые мы получили для начала.

Вычисления

>>> df.sum()
Close Amount    538739.51
dtype: float64


>>> df.min()
Date Received              2014-01-01 00:00:00
Incident Date              2011-08-24 08:30:00
Airport Code                                 -
Airport Name      Albert J Ellis, Jacksonville
Airline Name                                 -
Claim Type                                   -
Claim Site                                   -
Item Category                                -
Close Amount                                 0
Disposition                                  -


>>> df.max()
Date Received                       2014-12-31 00:00:00
Incident Date                       2014-12-31 00:00:00
Airport Code                                        ZZZ
Airport Name                 Yuma International Airport
Airline Name                                 XL Airways
Claim Type                              Property Damage
Claim Site                                        Other
Item Category    Travel Accessories; Travel Accessories
Close Amount                                    25483.4
Disposition                                      Settle
dtype: object

Booleans

Найдите все строки, в которых Close Amount больше нуля. Это полезно, потому что мы хотим увидеть несколько паттеринов, где сумма действительно положительна, и показать, как работают условные операторы.

>>> df[df['Close Amount'] > 0].describe()
       Close Amount
count   2360.000000
mean     228.279453
std      743.720179
min        1.250000
25%       44.470000
50%      100.000000
75%      240.942500
max    25483.440000

Группировка

В этом примере мы рассмотрим, как группировать по значениям одного столбца.

Объект Groupby - это промежуточный шаг, который позволяет нам агрегировать несколько строк, которые имеют что-то общее - в данном случае, значение диспозиции. Это полезно, поскольку мы получаем вид с высоты птичьего полета на различные категории данных. В конечном итоге мы используем describe() для просмотра нескольких агрегатов одновременно.

>>> grp = df.groupby(by='Disposition')
>>> grp.describe()
                Close Amount
                       count        mean          std   min       25%      50%       75%       max
Disposition
-                     3737.0    0.000000     0.000000  0.00    0.0000    0.000    0.0000      0.00
Approve in Full       1668.0  158.812116   314.532028  1.25   32.9625   79.675  159.3375   6183.36
Deny                  2758.0    0.000000     0.000000  0.00    0.0000    0.000    0.0000      0.00
Settle                 692.0  395.723844  1268.818458  6.00  100.0000  225.000  425.6100  25483.44

Группировка по нескольким столбцам:

>>> grp = df.groupby(by=['Disposition', 'Claim Site'])
>>> grp.describe()
                                Close Amount
                                       count         mean          std     min       25%       50%        75%       max
Disposition     Claim Site
-               -                       34.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Bus Station              2.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Checked Baggage       2759.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Checkpoint             903.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Motor Vehicle           28.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Other                   11.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
Approve in Full Checked Baggage       1162.0   113.868072   192.166683    1.25   25.6600    60.075   125.9825   2200.00
                Checkpoint             493.0   236.643367   404.707047    8.95   60.0000   124.000   250.1400   6183.36
                Motor Vehicle            9.0  1591.428889  1459.368190  493.80  630.0000   930.180  1755.9800   5158.05
                Other                    4.0   398.967500   358.710134   61.11  207.2775   317.385   509.0750    899.99
Deny            -                        4.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Checked Baggage       2333.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Checkpoint             407.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
                Motor Vehicle            1.0     0.000000          NaN    0.00    0.0000     0.000     0.0000      0.00
                Other                   13.0     0.000000     0.000000    0.00    0.0000     0.000     0.0000      0.00
Settle          Checked Baggage        432.0   286.271968   339.487254    7.25   77.0700   179.995   361.5700   2500.00
                Checkpoint             254.0   487.173031  1620.156849    6.00  166.9250   281.000   496.3925  25483.44
                Motor Vehicle            6.0  4404.910000  7680.169379  244.00  841.8125  1581.780  2215.5025  20000.00

Плотирование

Хотя агрегаты по группам данных - один из лучших способов получить представление, визуализация данных позволяет вычленить закономерности на странице и проста для тех, кто не так хорошо знаком с агрегатными значениями. Правильно отформатированные визуализации очень важны для передачи смысла данных, и приятно видеть, что в Pandas есть некоторые из этих функций:

>>> df.plot(x='Incident Date', y='Close Amount')
>>> plt.show()

Дата инцидента по сумме закрытия

Экспорт преобразованных данных

Наконец, нам может понадобиться зафиксировать либо наши исходные данные, либо агрегаты в виде DataFrame в формате файла, отличном от того, с которого мы начали, поскольку Pandas не ограничивает вас в записи обратно в тот же формат файла.

Наиболее распространенным плоским файлом для записи в Pandas будет .csv. Судя по визуализации, похоже, что стоимость претензий TSA, хотя иногда и очень высокая из-за некоторых выбросов, в 2015 году улучшилась. Возможно, нам следует рекомендовать сравнить кадровые и процедурные изменения, чтобы продолжить движение в этом направлении, и более детально изучить, почему у нас больше инцидентов в определенное время суток.

Как и для загрузки данных, Pandas предлагает несколько методов записи данных в файл в различных форматах. Запись в файл Excel немного сложнее, чем другие, поэтому давайте запишем в еще более переносимый формат: CSV. Чтобы записать преобразованный набор данных в новый файл CSV:

>>> df.to_csv(path_or_buf='claims-2014.v1.csv')

Финальные заметки

Здесь мы увидели интересный и мощный рабочий процесс. Мы совершили круговой путь от правительственного excel-файла до Python, через довольно мощную визуализацию данных и обратно к .csv-файлу, который может быть более универсальным - и все это благодаря возможностям Pandas. Далее мы рассмотрели три центральных объекта Pandas - DataFrames, Series и dtypes. И самое главное, мы получили более глубокое понимание интересного, реального набора данных.

Это основные понятия, которые необходимо понимать при работе с Pandas, и теперь вы можете задавать интеллектуальные вопросы (себе или Google) об этих различных объектах. Этот пример использования данных TSA показал нам, для чего именно подходит Pandas: исследование, анализ и агрегирование данных для получения выводов.

Анализ и исследование данных важны практически в любой области, но они особенно полезны для Data Scientists и специалистов по искусственному интеллекту, которым может потребоваться дробление и очистка данных очень специфическими, мелкозернистыми способами, например, получение скользящих средних на биржевых тиках. Кроме того, некоторые задачи могут нуждаться в автоматизации, а это может оказаться сложным или дорогостоящим в таких разросшихся приложениях, как Excel или Google Sheets, которые не могут предложить всю функциональность Pandas с полной мощью Python.

Представьте себе, что вы говорите бизнес-администратору, что, возможно, ему больше никогда не придется запускать этот сломанный макрос электронной таблицы! Как только анализ автоматизирован, его можно развернуть как сервис или применить к сотням тысяч записей, поступающих из базы данных. Кроме того, Pandas можно использовать для принятия важных решений после установления статистических ассоциаций между шаблонами, как это происходит каждый день.

Далее не забудьте ознакомиться с обширными библиотеками баз данных Python (например, SQLalchemy) или API-клиентами (например, Google Sheets/Slides Python Client или Airtable API для представления результатов экспертам в области). Возможности безграничны, и они только расширяются благодаря развитым библиотекам Python и активному сообществу.

Вернуться на верх