Библиотека Pandas и датафрейм | Анализ и обработка данных

Библиотека Pandas

Все курсы > Анализ и обработка данных > Занятие 1

Мы начинаем курс анализа и обработки данных. На двух предыдущих курсах мы, во-первых, получили общее представление о том, как устроено машинное обучение, и, во-вторых, приобрели достаточно продвинутые навыки в программировании на Питоне.

Курс анализа данных — это первый курс, в рамках которого мы переходим непосредственно к работе над построением моделей.

Содержание занятия

Для того чтобы лучше понимать содержание этого курса давайте вначале рассмотрим этапы построения модели.

Задача машинного обучения

Ниже представлена общая последовательность работы над задачей машинного обучения.

этапы решения задачи машинного обучения

Описанный процесс принято называть пайплайном, то есть порядком действий (от англ. pipeline, трубопровод, конвейер), которые необходимо выполнять для построения модели. Подробнее рассмотрим некоторые из этих этапов.

Этап 1. Постановка задачи и определение метрики

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

Этап 2. Получение данных

Важный этап. Хотя на этом курсе мы будем использовать уже готовые (зачастую учебные) датасеты, стоит помнить, что получение данных (data gathering) не происходит само собой и во многом от того как и какие данные собраны будет зависеть конечный результат (на который не смогут повлиять ни качественный EDA, ни сложный алгоритм машинного обучения).

Этап 3. Исследовательский анализ данных

В рамках EDA нам нужно решить три основных задачи: описать данные, найти отличия и выявить взаимосвязи. Описание данных позволяет понять, о каких данных идет речь, а также выявить недостатки в данных (с которыми мы справляемся на этапе обработки). Отличия и взаимосвязи в данных — основа для построения модели, это то, за что модель «цепляется», чтобы выдать верный числовой результат, правильную классификацию или кластер.

Для решения этих задач наилучшим образом подходят средства визуализации и описательная статистика. Этим мы займемся во втором разделе.

Отдельно хочется сказать про baseline models, простые модели, которые мы строим в самом начале работы. Они позволяют понять какой результат мы можем получить, не вкладывая дополнительных усилий в работу с данными, а затем отталкиваться от этого результата для обработки данных и построения более сложных моделей.

Базовые модели мы начнем строить на курсе по оптимизации.

Этап 4. Обработка данных

Как уже было сказано, на этапе EDA зачастую становится очевидно, что в данных есть недостатки, которые сильно повляют на качество модели или в целом не позволят ее обучить.

Очистка данных: ошибки и пропуски

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

Преобразование данных

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

Преобразование количественных и категориальных данных рассматривается в четвертом разделе.

Конструирование и отбор признаков, понижение размерности

Еще одним важным этапом является конструирование признаков, а также отбор признаков и понижение размерности. В рамках этого курса мы затронем лишь базовые способы конструирования признаков. Более сложные вопросы отбора признаков и понижения размерности мы отложим на потом.

Этап 5. Моделирование и оценка результата

Когда данные готовы, их можно загружать в модель, обучать эту модель и оценивать результат.

Здесь важно сказать, что это итеративный (iterative) или циклический процесс. Многие из описанных выше шагов могут повторяться. В частности, построение модели может привести к необходимости дополнительной обработки данных. Кроме того, разные алгоритмы требуют разной подготовки данных (например, линейные модели требуют масштабирования данных, а для деревьев решений этого не нужно).

При этом прежде чем приступить к анализу и обработке данных важно освоить библиотеку Pandas. Именно этим мы и займемся в начале курса.

Про библиотеку Pandas

библиотека Pandas

Библиотека Pandas — это ключевой инструмент для анализа данных на Питоне. Она позволяет работать с данными, представленными в табличной форме, а также временными рядами. Как вы уже видели, Pandas легко интегрируется с matplotlib, seaborn, sklearn и другими библиотеками.

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

Откроем ноутбук к этому занятию

Объекты DataFrame и Series

В Pandas есть два основных объекта: DataFrame и Series. Слегка упрощая, можно сказать, что DataFrame — это таблица (и соответственно двумерный массив), а Series — столбец этой таблицы (а значит одномерный массив).

библиотека Pandas, анатомия датафрейма

Индекс (index), столбцы (columns) и значения (values) датафрейма мы разберем чуть позднее, а сейчас давайте посмотрим на способы создания датафрейма.

Создание датафрейма

Способ 1. Создание датафрейма из файла

Датафрейм можно создать, импортировав файлы различных форматов. Мы уже делали так с файлами в формате .csv с помощью функции pd.read_csv(). Аналогичным образом можно импортировать файлы и в других форматах, например MS Excel или html. Рассмотрим несколько примеров.

Файл .csv в zip-архиве. Если в zip-архиве содержится только один файл, его можно напрямую подгрузить в Pandas. Вначале скачаем необходимые данные.

После скачивания не забудьте подгрузить данные в сессионное хранилище Google Colab.

импорт датасета "Титаник" из zip-архива

Как вы наверное узнали, речь идет о датасете «Титаник».

MS Excel. Похожим образом мы можем импортировать файлы в формате Excel.

Теперь используем функцию pd.read_excel() для импорта файла.

импорт датасета про цветы ириса из файла в формате Excel

С датасетом про цветы ириса мы также уже знакомы.

Дополнительно зачему, что файлы можно хранить локально на своем компьютере (если вы используете Jupyter Notebook), импортировать в сессионное хранилище Google Colab или передать в функцию импорта ссылку на файл в Интернете.

Файл в формате html. Данные можно загружать не только из файла, но и брать из Интернета. Для этого подойдет функция read_html(). По большому счету речь идет о примере несложного веб-скрапинга (web scraping), то есть получения информации с веб-страниц в автоматизированном режиме.

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

таблица World Population страницы Википедии про население Земли

Посмотрим на второй полученный результат.

таблица World Population в формате датафрейма библиотеки Pandas

Полученный датафрейм требует форматирования. Подробнее приведенные ниже методы мы будем разбирать в течение занятия.

отформатированный датафрейм World Population

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

Способ 2. Подключение к базе данных SQL

Библиотека Pandas позволяет получать информацию напрямую из базы данных SQL. В качестве примера возьмем популярную учебную базу данных Chinook, в которой содержится информация о магазине, торгующем цифровыми записями (digital media store).

Ниже представлена схема этой реляционной базы данных (relational database schema).

часть схемы реляционной базы данных Chinook

Тема реляционных баз данных и SQL выходит за рамки сегодняшнего занятия, однако для полноты изложения скажу, что такая база данных называется реляционной (от англ. relation — «отношение, зависимость»), потому что ее таблицы взаимосвязаны.

Например, в таблице tracks (записи) в поле GenreId содержится идентификатор жанра. По этому идентификатору мы можем определить, к какому жанру принадлежит та или иная композиция, заглянув в таблицу genres, где каждому GenreId соответствует название определенного жанра.

SQL же расшифровывается как structured query language (язык структурированных запросов) и позволяет достаточно гибко создавать, извлекать и изменять данные из реляционных баз данных.

Попробуем подключить базу данных к нашему ноутбуку и написать очень простой запрос на SQL внутри кода на Питоне. Вначале скачаем базу данных chinook (архив нужно распаковать и подгрузить файл в формате .db).

датафрейм библиотеки Pandas с записями таблицы tracks базы данных chinook

Позднее в рамках курса мы поговорим еще про два формата: json и pickle.

Способ 3. Создание датафрейма из словаря

Кроме этого, и мы уже много раз так делали, библиотека Pandas позволяет создать датафрейм из словаря с помощью функции pd.DataFrame(). В этом случае ключи словаря будут названиями столбцов, а значения — элементами строк. Последние можно передать с помощью списков или массивов Numpy. Рассмотрим на примере.

Вначале подготовим данные.

Теперь создадим пустой словарь и поместим в него наши данные.

Наконец, создадим датафрейм с помощью функции pd.DataFrame().

датафрейм библиотеки Pandas, созданный из словаря

Способ 4. Создание датафрейма из 2D массива Numpy

Помимо этого, датафрейм можно создать из двумерного массива Numpy.

преобразование двумерного массива Numpy в датафрейм

Перейдем к структуре и свойствам датафрейма.

Структура и свойства датафрейма

Датафрейм библиотеки Pandas состоит из трех основных компонентов: строк (index), столбцов (columns) и значений (values).

Получить доступ к названиям столбцов можно с помощью атрибута columns.

Атрибут index описывает, каким образом идентифицируются строки.

С помощью атрибута values мы получаем доступ к значениям датафрейма.

Описание индекса и названия столбцов мы также можем получить с помощью атрибута axes (множественное от axis, ось) с индексами [0] и [1] соответственно.

В целом, полезно запомнить, что axis = 0 позволяет применить какой-либо метод к строкам датафрейма, а axis = 1, соответственно к столбцам.

Мы также можем посмотреть количество измерений, размерность и общее количество элементов датафрейма с помощью атрибутов ndim, shape и size соответственно.

Атрибут dtypes выдает тип данных каждого столбца.

Кроме того, с помощью метода .memory_usage() мы можем посмотреть объем занимаемой памяти по столбцам в байтах.

Индекс датафрейма

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

Присвоение индекса

Более того, этот индекс не обязательно должен быть числовым.

библиотека Pandas: как присвоить индекс датафрейма

Этот индекс можно сбросить с помощью метода .reset_index().

сбросить индекс датафрейма

Как мы видим, прошлый индекс стал отдельным столбцом. Снова сделаем этот столбец индексом с помощью метода .set_index().

установить индекс датафрейма

Еще раз сбросим индекс, но на этот раз не будем делать его отдельным столбцом. Для этого передадим методу .reset_index() параметр drop = True.

сбросить индекс датафрейма и удалить столбец индекса

Собственный индекс можно создать, просто поместив новые значения в атрибут index.

задать индекс датафрейма через атрибут index

Многоуровневый индекс

Многоуровневый (MultiIndex) или иерархический (hierarchical) индекс позволяет задать несколько уровней (levels) для индексации строк или столбцов. «Внешний» индекс объединяет несколько элементов «внутреннего» индекса.

Вначале подготовим данные для многоуровневого индекса строк.

Проделаем аналогичную работу для столбцов.

Теперь создадим иерархический индекс для строк и столбцов с помощью функции pd.MultiIndex.from_tuples().

Наконец остается передать эти индексы в атрибуты index и columns и вывести результат.

библиотека Pandas, датафрейм с многоуровневым/иерархическим индексом

Как мы видим страны (code) теперь разбиты на континенты (region), а информация о них — на текстовые (names) и числовые (data) данные.

датафрейма с одноуровневым индексом по строкам и столбцам

Преобразование в другие форматы

Получившийся датафрейм можно преобразовать в словарь с помощью метода .to_dict().

Аналогично, метод .to_numpy() преобразовывает данные в массив Numpy.

Кроме того, мы можем сохранить датафрейм в файл (в Google Colab он появится в сессионном хранилище). Например, это может быть файл в формате .csv и тогда необходимо использовать функцию .to_csv().

.csv файл в сессионном хранилище Google Colab

Метод .to_list() позволяет преобразовать объект Series (столбец датафрейма) в список.

Применить метод .to_list() к датафрейму не получится.

Создание Series

Создание Series из списка

Объект Series можно создать из списка. Возьмем следующий список с названиями стран.

Передадим его в функцию pd.Series().

Обратите внимание, что для объекта Series был автоматически создан числовой индекс. С его помощью мы можем получить доступ к элементам этого объекта.

Создание Series из словаря

Помимо списка, объект Series можно создать из словаря. Создадим словарь, в котором коды стран будут ключами, а их названия — значениями.

Передадим этот словарь в функцию pd.Series(). Ключи станут индексами, а значения — элементами объекта.

Доступ к элементам будет осуществляться теперь уже по коду отдельной страны.

Доступ к строкам, столбцам и элементам

Поговорим про способы обращения к строкам, столбцам и элементам датафрейма.

Циклы в датафрейме

Цикл for позволяет получить доступ к названиям столбцов датафрейма.

Метод .iterrows() возвращает индекс строки и ее содержимое в формате Series.

Получить доступ к элементам одной строки можно по индексу объекта Series (то есть по названиям столбцов исходного датафрейма).

Доступ к столбцам

В отличие от объекта Series в датафрейме через квадратные скобки мы получаем доступ к его столбцам.

Доступ к столбцу можно также получить, указав название датафрейма и через точку название искомого столбца.

Как уже было сказано, отдельные столбцы в датафрейме имеют тип данных Series.

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

доступ к столбцам датафрейма через двойные квадратные скобки

Так мы можем получить доступ к нескольким столбцам.

доступ к двум столбцам датафрейма через двойные квадратные скобки

Доступ к столбцам можно также получить с помощью метода .filter(), передав параметру items список с необходимыми нам столбцами.

доступ к столбцам датафрейма через метод .filter()

Доступ к строкам

Получить доступ к строкам можно через срез индекса.

библиотека Pandas, доступ к строкам датафрейма

Методы .loc[] и .iloc[]

Метод .loc[]

Метод .loc[] позволяет получить доступ к строкам и столбцам через их названия (label-based location). Например, выведем первые три строки и первые три столбца датафрейма про страны.

библиотека Pandas, метод .loc[]

Через двоеточие, как и в Numpy, мы можем вывести все строки или все столбцы датафрейма.

двоеточие и метод .loc[]

Метод .loc[] также поддерживает значения Boolean.

логические значения и метод .loc[]

Метод .get_loc() позволяет узнать порядковый номер (начиная с нуля) строки или столбца по их индексу и названию соответственно. Для того чтобы узнать порядковый номер строки, метод .get_loc() нужно использовать совместно с атрибутом index.

Теперь выведем номер столбца country. Для этого нам понадобится атрибут columns.

Метод .iloc[]

Метод .iloc[] действует примерно также, как и .loc[], с тем отличием, что он основывается на числовом индексе (integer-based location).

библиотека Pandas, метод .iloc[]

В методе .iloc[] можно использовать срезы.

метод .iloc[] и срезы

К столбцам удобно обращаться по их названиям, к строкам — по порядковому номеру (числовому индексу). Для того чтобы это реализовать, мы можем объединить двойные квадратные скобки и метод .iloc[].

двойные скобки для столбцов и метод .iloc[] для строк

Многоуровневый индекс и методы .loc[] и .iloc[]

Поговорим про применение методов .loc[] и .iloc[] к датафрейму с многоуровневым индексом.

библиотека Pandas, многоуровневый индекс и методы .loc[] и .iloc[]

Для доступа к первой строке передадим методу .loc[] соответствующий двойной индекс.

Мы также можем передать значения в форме кортежей как для строк, так и для столбцов.

Доступ к строкам можно получить, указав внутри кортежа название региона и список с кодами стран.

доступ по многоуровневому индексу с указанием внешнего и внутренних индексов

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

доступ по многоуровневому индексу с указанием только внешнего индекса

Аналогичным образом мы можем получить доступ к столбцам.

доступ по многоуровневому индексу к столбцам с помощью метода .loc[]

Метод .iloc[], при этом, игнорирует структуру иерархического индекса и использует простой числовой индекс.

Метод .xs()

Метод .xs() (от англ. cross-section, срез) позволяет получить доступ к определенному уровню иерархического индекса. Начнем со строк.

доступ к уровню строк многоуровневого индекса с помощью метода .xs()

Перейдем к столбцам и выберем names и country (по сути мы выбираем столбец country) на первом и втором уровнях соответственно.

доступ к столбцам по многоуровневому индексу с помощью метода .xs()

Кроме того, мы можем соединить два метода .xs() и одновременно получить доступ и к строкам, и к столбцам.

доступ к строкам и столбцам по многоуровневому индексу с помощью метода .xs()

Вернем датафрейму одноуровневый индекс.

библиотека Pandas, одноуровневый датафрейм

Метод .at[]

Метод .at[] подходит для извлечения или записи одного значения датафрейма.

Фильтры

Логическая маска

Как и в случае с массивом Numpy, мы можем создать логическую маску (Boolean mask) датафрейма, в которой нежелательные значения будут помечены как False.

Применив эту маску к исходному датафрейму, мы получим только те значения, которые помечены как True.

логическая маска датафрейма с одним условием

Мы можем применить к датафрейму две маски, объединенные, например, логическим оператором И.

логическая маска датафрейма с двумя условиями

Приведу еще один вариант синтаксиса. Его удобно использовать, если у вас есть множество условий, по которым вы хотите отфильтровать датафрейм.

логическая маска датафрейма с двумя условиями, еше один вариант синтаксиса

Метод .query()

Метод .query() позволяет задавать условие фильтрации «своими словами».

метод .query() в библиотеке Pandas

При фильтрации по строковым значениям (которые записываются в кавычках), необходимо использовать различающиеся кавычки: двойные для метода .query() и одинарные для строкового значения или наоборот.

двойные кавычки при фильтрации по строковым значениям в библиотеке Pandas

Другие способы фильтрации

С помощью метода .isin() мы можем проверить наличие нескольких значений в определенном столбце, а затем использовать результат в качестве логической маски.

метод .isin() для фильтрации значений в датафрейме библиотеки Pandas

Похожим образом можно использовать метод .startswith().

метод .startswith() для фильтрации значений в датафрейме библиотеки Pandas

Метод .nlargest() позволяет найти строки с наибольшим значением в определенном столбце.

метод .nlargest() для фильтрации значений в датафрейме библиотеки Pandas

Метод .nsmallest() аналогичным образом находит наименьшие значения.

Метод .argmax() выводит индекс строки, в которой в определенном столбце содержится наибольшее значение.

Посмотрим, какой стране соответствует этот индекс.

метод .argmax() для фильтрации значений в датафрейме библиотеки Pandas

Метод .argmin() выполняет обратное действие.

Вспомним, что в метод .loc[] можно передать тип данных Boolean. Используем это свойство для создания фильтра.

метод .loc[] для фильтрации значений в датафрейме библиотеки Pandas

Метод .filter(), если использовать параметр like, ищет совпадения с искомой фразой в индексе (если axis = 0) или названии столбцов (если axis = 1).

метод .filter() для фильтрации значений в датафрейме библиотеки Pandas

Очевидно, если указать параметр axis = 1, выведется индекс, потому что именно в нем есть буквосочетание ZA.

Сортировка

Для сортировки значений в датафрейме библиотеки Pandas используется метод .sort_values(). Этому методу мы можем передать, среди прочих, следующие параметры:

  • by — по какому столбцу или столбцам вести сортировку
  • inplace — сохранять ли результат
  • ascending — в восходящем или нисходящем порядке сортировать

Рассмотрим два примера.

метод .sort_values() для сортировки по одному столбцу по возрастанию
метод .sort_values() для сортировки по двум столбцам по убыванию

Кроме того, можно отсортировать строки по индексу с помощью метода .sort_index().

метод .sort_index() библиотеки Pandas

На этом завершим сегодняшнее занятие.

Подведем итог

На первом занятии по анализу и обработке данных мы рассмотрели из каких этапов состоит решение задачи машинного обучения и начали углубленное изучение библиотеки Pandas.

В частности, мы узнали про типы объектов библиотеки Pandas (датафрейм и Series), способы их создания, структуру и свойства. Кроме того, мы рассмотрели возможности доступа к строкам, столбцам и элементам датафрейма.

Вопросы для закрепления

Вопрос. Зачем нужны baseline-модели при решении ML задачи?

Ответ: слово baseline, в частности, переводится как базовый или исходный уровень и baseline-модель — это своего рода точка отсчета, простая модель, которая позволяет сравнить, насколько нам удается улучшить результат, применяя различные преобразования данных и настраивая алгоритмы.

Вопрос. Чем объект DataFrame отличается от Series?

Ответ: ключевое отличие в том, что DataFrame — это двумерный массив (даже если в нем только один столбец), Series, соответственно, одномерный.

Методы многих классов (например, класс LinearRegression в Sklearn) требуют на входе именно DataFrame (или двумерный массив Numpy), а не Series.

Вопрос. В чем отличие между методами .loc[] и .iloc[]?

Ответ: метод .loc[] позволяет найти строки или столбцы датафрейма, основываясь на их названии, метод .iloc[] выполняет ту же функцию, однако на входе принимает числовой индекс.

На следующем занятии мы разберем возможности изменения, соединения и группировки датафреймов.