6.2. Модуль pandas
В этой статье вы познакомитесь с библиотекой pandas — одним из ключевых инструментов для анализа данных в Python. Вы узнаете, как создавать и использовать объекты Series и DataFrame, считывать данные из файлов, фильтровать и сортировать таблицы, выполнять агрегирование и строить простые визуализации. Библиотека pandas построена на базе numpy и предоставляет удобный интерфейс для работы с табличными структурами, которые встречаются почти во всех проектах, связанных с анализом, отчётами и машинным обучением.
Ключевые вопросы статьи
- Как установить и подключить библиотеку
pandas?- Что такое объекты
SeriesиDataFrameи как с ними работать?- Как фильтровать, сортировать и агрегировать данные?
- Как создавать и изменять табличные структуры в pandas?
- Как визуализировать табличные данные с помощью библиотеки
matplotlib?
Как установить и подключить библиотеку pandas
Для работы с табличными структурами данных в Python чаще всего используют библиотеку pandas. Она построена на основе numpy и обеспечивает удобные инструменты для анализа и обработки данных.
Чтобы начать использовать pandas, установите её через командную строку:
pip install pandas
Во всех примерах в этой статье предполагается, что библиотеки numpy и pandas импортированы следующим образом:
import numpy as np
import pandas as pd
Далее вы познакомитесь с двумя основными структурами данных библиотеки pandas — объектами Series и DataFrame — и научитесь создавать и обрабатывать таблицы.
Что такое объекты Series и DataFrame и как с ними работать
В библиотеке pandas определены два основных класса объектов для работы с данными:
Series— одномерный массив, способный хранить значения любого типа. По своей структуре напоминает словарь: каждому значению присваивается метка (индекс), которая может быть как числом, так и строкой.DataFrame— двумерная таблица, в которой строки и столбцы имеют имена. Каждый столбец — это объект классаSeries, а сами данные удобно организованы для анализа и преобразований.
Создание и работа с этими объектами лежит в основе большинства операций в pandas.
Создание Series
Создать Series можно с помощью конструктора:
s = pd.Series(data, index=index)
dataможет быть массивомnumpy, словарём или скаляром (числом).index— список меток, по умолчанию это целые числа от0доn-1.
Примеры:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print(s)
s = pd.Series(np.linspace(0, 1, 5))
print(s)
# Вывод программы
# a 0
# b 1
# c 2
# d 3
# e 4
# dtype: int32
# 0 0.00
# 1 0.25
# 2 0.50
# 3 0.75
# 4 1.00
# dtype: float64
Если data — словарь, а index не задан, то в качестве меток используются ключи словаря:
d = {"a": 10, "b": 20, "c": 30, "g": 40}
print(pd.Series(d))
# Вывод программы:
# a 10
# b 20
# c 30
# g 40
# dtype: int64
Если передать index, не совпадающий с ключами словаря, то отсутствующие значения будут заменены на NaN:
print(pd.Series(d, index=["a", "b", "c", "d"]))
# Вывод программы
# a 10.0
# b 20.0
# c 30.0
# d NaN
# dtype: float64
Если data — число, обязательно передаётся index, определяющий количество элементов:
index = ["a", "b", "c"]
print(pd.Series(5, index=index))
# Вывод программы
# a 5
# b 5
# c 5
# dtype: int64
Индексация, срезы и арифметика
Объекты Series поддерживают индексирование, срезы и математические операции:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print(s["a"]) # Один элемент
print(s[["a", "d"]]) # Несколько элементов
print(s[1:]) # Срез
print(s + s) # Поэлементное сложение
# Вывод программы
# Выбор одного элемента
# 0
# Выбор нескольких элементов
# a 0
# d 3
# dtype: int32
# Срез
# b 1
# c 2
# d 3
# e 4
# dtype: int32
# Поэлементное сложение
# a 0
# b 2
# c 4
# d 6
# e 8
# dtype: int32
Фильтрация
Можно использовать булевы условия для отбора значений:
print(s[s > 2])
# Вывод программы
# Фильтрация
# d 3
# e 4
# dtype: int32
Атрибуты Series
У объекта Series есть полезные свойства:
s.name = "Данные"
s.index.name = "Индекс"
print(s)
# Вывод программы
# Индекс
# a 0
# b 1
# c 2
# d 3
# e 4
# Name: Данные, dtype: int32
Создание и работа с DataFrame
DataFrame — это таблица с именованными столбцами и индексами строк. Создать DataFrame можно из словаря списков:
students_marks_dict = {
"student": ["Студент_1", "Студент_2", "Студент_3"],
"math": [5, 3, 4],
"physics": [4, 5, 5]
}
students = pd.DataFrame(students_marks_dict)
print(students)
# Вывод программы
# student math physics
# 0 Студент_1 5 4
# 1 Студент_2 3 5
# 2 Студент_3 4 5
Индексы строк и столбцов
У объекта DataFrame есть индексы по строкам и по столбцам. Их можно получить с помощью свойств index и columns:
print(students.index)
print(students.columns)
# Вывод программы
# RangeIndex(start=0, stop=3, step=1)
# Index(['student', 'math', 'physics'], dtype='object')
По умолчанию строки нумеруются от 0. При необходимости индексы можно переопределить вручную:
students.index = ["A", "B", "C"]
Каждый столбец DataFrame на самом деле представляет собой отдельный объект Series. Поэтому, если обратиться к одному столбцу по его имени, мы получим объект этого типа:
print(type(students["student"]))
# <class 'pandas.core.series.Series'>
Для доступа к строкам по индексам используют .loc[], включая срезы:
print(students.loc["B":])
# Вывод программы
# student math physics
# B Студент_2 3 5
# C Студент_3 4 5
Как фильтровать, сортировать и агрегировать данные
В pandas объект Series можно создать из массива numpy, словаря или даже одного значения. Параметр index задаёт метки осей (индексы) и передаётся в виде списка. Метками могут быть числа, но чаще — строки.
Если в качестве data используется массив numpy, длина index должна совпадать с числом элементов. Если индекс не задан, он формируется автоматически как последовательность от 0 до len(data) - 1:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print(s)
print()
s = pd.Series(np.linspace(0, 1, 5))
print(s)
# Вывод
# a 0
# b 1
# c 2
# d 3
# e 4
# dtype: int32
#
# 0 0.00
# 1 0.25
# 2 0.50
# 3 0.75
# 4 1.00
# dtype: float64
Объект Series во многом напоминает словарь: каждому значению соответствует собственная метка.
Если data — это словарь, а index не задан, в качестве индексов будут использованы ключи словаря. Если index задан и содержит значения, которых нет среди ключей словаря, то в соответствующих ячейках будет стоять NaN — стандартное обозначение отсутствующих данных в pandas:
d = {"a": 10, "b": 20, "c": 30, "g": 40}
print(pd.Series(d))
print()
print(pd.Series(d, index=["a", "b", "c", "d"]))
# Вывод
# a 10
# b 20
# c 30
# g 40
# dtype: int64
#
# a 10.0
# b 20.0
# c 30.0
# d NaN
# dtype: float64
Если data — это одно значение, параметр index обязательно нужен. Серия будет состоять из повторяющихся значений:
index = ["a", "b", "c"]
print(pd.Series(5, index=index))
# Вывод
# a 5
# b 5
# c 5
# dtype: int64
С объектами Series можно работать так же, как с массивами numpy: выполнять срезы, индексацию, поэлементные операции:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print("Выбор одного элемента")
print(s["a"])
print("Выбор нескольких элементов")
print(s[["a", "d"]])
print("Срез")
print(s[1:])
print("Поэлементное сложение")
print(s + s)
# Вывод
# Выбор одного элемента
# 0
# Выбор нескольких элементов
# a 0
# d 3
# dtype: int32
# Срез
# b 1
# c 2
# d 3
# e 4
# dtype: int32
# Поэлементное сложение
# a 0
# b 2
# c 4
# d 6
# e 8
# dtype: int32
Можно отфильтровать данные по условию:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print("Фильтрация")
print(s[s > 2])
# Вывод
# Фильтрация
# d 3
# e 4
# dtype: int32
У объектов Series есть два полезных атрибута:
name— название набора данных;index.name— имя оси индексов:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
s.name = "Данные"
s.index.name = "Индекс"
print(s)
# Вывод
# Индекс
# a 0
# b 1
# c 2
# d 3
# e 4
# Name: Данные, dtype: int32
Как создавать и изменять табличные структуры в pandas
Обычно табличные данные хранятся в файлах. Такие наборы принято называть датасетами (англ. dataset, набор данных). Файлы с данными могут быть в разных форматах: CSV, Excel, JSON, SQL и другие. Библиотека pandas поддерживает как чтение, так и сохранение таблиц в этих форматах.
Как считывать и сохранять данные в различных форматах (CSV, Excel, JSON)
Рассмотрим несколько примеров:
CSV-файлы
- Считывание:
pd.read_csv("имя_файла.csv") - Сохранение:
df.to_csv("имя_файла.csv")
Excel-файлы (формат 2007+)
- Считывание:
pd.read_excel("имя_файла.xlsx") - Сохранение:
df.to_excel("имя_файла.xlsx")
JSON-файлы
- Считывание:
pd.read_json("имя_файла.json") - Сохранение:
df.to_json("имя_файла.json")
Полный список поддерживаемых форматов и настроек доступен в официальной документации.
CSV остаётся одним из самых популярных форматов хранения табличных данных. Это обычный текстовый файл, в котором значения разделены символами (например, запятой или точкой с запятой), а строки идут с новой строки. Обычно первая строка содержит заголовки столбцов.
Пример содержимого CSV-файла:
"gender","race/ethnicity","parental level of education","lunch","test preparation course","math score","reading score","writing score"
"female","group B","bachelor's degree","standard","none","72","72","74"
"female","group C","some college","standard","completed","69","90","88"
Для дальнейшей работы скачайте данный файл с датасетом. Получим датасет из CSV-файла с данными о студентах:
import numpy as np
import pandas as pd
students = pd.read_csv("StudentsPerformance.csv")
Полученный объект students относится к классу DataFrame.
Для получения первых n строк датасета используется метод head(n). По умолчанию возвращается пять первых строк:
print(students.head())
# Вывод программы
# gender race/ethnicity ... reading score writing score
# 0 female group B ... 72 74
# 1 female group C ... 90 88
# 2 female group B ... 95 93
# 3 male group A ... 57 44
# 4 male group C ... 78 75
# [5 rows x 8 columns]
Для получения последних n строк используется метод tail(n). По умолчанию возвращается пять последних строк:
print(students.tail(3))
# Вывод программы
# gender race/ethnicity ... reading score writing score
# 997 female group C ... 71 65
# 998 female group D ... 78 77
# 999 female group D ... 86 86
#
# [3 rows x 8 columns]
Для получения части датасета можно использовать срез:
print(students[10:13])
# Вывод программы
# gender race/ethnicity ... reading score writing score
# 10 male group C ... 54 52
# 11 male group D ... 52 43
# 12 female group B ... 81 73
#
# [3 rows x 8 columns]
В качестве индекса можно использовать условия для фильтрации данных. Выберем первые 5 значений по математике у студентов, прошедших подготовку:
print(students[students["test preparation course"] == "completed"]["math score"].head())
# Вывод программы
#
# 1 69
# 6 88
# 8 64
# 13 78
# 18 46
# Name: math score, dtype: int64
Выведем пять лучших результатов тестов по трём дисциплинам для предыдущей выборки с помощью сортировки методом sort_values(). Сортировка по умолчанию производится в порядке возрастания значений. Для сортировки по убыванию в именованный аргумент ascending передаётся значение False.
with_course = students[students["test preparation course"] == "completed"]
print(with_course[["math score", "reading score", "writing score"]]
.sort_values(["math score", "reading score", "writing score"], ascending=False)
.head())
# Вывод программы
# math score reading score writing score
# 916 100 100 100
# 149 100 100 93
# 625 100 97 99
# 623 100 96 86
# 114 99 100 100
Сортировка по новой колонке total_score, которую добавим вручную:
students["total score"] = (students["math score"]
+ students["reading score"]
+ students["writing score"])
print(students.sort_values("total score", ascending=False).head())
# Вывод программы
#
# gender race/ethnicity ... writing score total score
# 916 male group E ... 100 300
# 458 female group E ... 100 300
# 962 female group E ... 100 300
# 114 female group E ... 100 299
# 179 female group D ... 100 297
#
# [5 rows x 9 columns]
Чтобы в таблицу добавить колонку, подойдёт метод assign(). Данный метод даёт возможность создавать колонки при помощи лямбда-функции.
Примечание
Данный метод возвращает новую таблицу, а не меняет исходную.
Перепишем предыдущий пример с использованием assign():
scores = students.assign(total_score=lambda x: x["math score"]
+ x["reading score"]
+ x["writing score"])
print(scores.sort_values("total_score", ascending=False).head())
# Вывод программы
#
# gender race/ethnicity ... writing score total_score
# 916 male group E ... 100 300
# 458 female group E ... 100 300
# 962 female group E ... 100 300
# 114 female group E ... 100 299
# 179 female group D ... 100 297
Группировка и агрегирование данных
Метод groupby() позволяет сгруппировать записи по признаку. Например, узнаем, сколько студентов разного пола прошли подготовку:
print(students.groupby(["gender", "test preparation course"])["writing score"].count())
# Вывод программы
#
# gender test preparation course
# female completed 184
# none 334
# male completed 174
# none 308
# Name: race/ethnicity, dtype: int64
Для вычисления сводных значений используем агрегирующие функции (среднее, медиана, сумма и т. п.).
Например:
agg_functions = {"math score": ["mean", "median"]}
print(students.groupby(["gender", "test preparation course"]).agg(agg_functions))
# Вывод программы
#
# math score
# mean median
# gender test preparation course
# female completed 67.195652 67.0
# none 61.670659 62.0
# male completed 72.339080 73.0
# none 66.688312 67.0
Как визуализировать табличные данные с помощью matplotlib
Для построения графиков pandas использует библиотеку matplotlib. Чтобы начать с ней работать, необходимо:
- Установить библиотеку.
- Добавить импорт в начало программы.
Для установки выполним команду:
pip install matplotlib
А затем импортируем:
import matplotlib.pyplot as plt
Пример: гистограмма распределения баллов
Построим гистограмму, отображающую распределение количества студентов по баллам за тест по математике:
plt.hist(students["math score"], label="Тест по математике")
plt.xlabel("Баллы за тест")
plt.ylabel("Количество студентов")
plt.legend()
plt.show()
В результате выполнения кода отобразится график, где по оси X — баллы, а по оси Y — количество студентов, набравших соответствующий результат.
Ещё по теме
Для более детального изучения библиотеки numpy рекомендуем почитать документацию.
Что дальше
В этой статье вы освоили базовые приёмы работы с табличными данными в библиотеке pandas.
Вы узнали, чем объекты Series и DataFrame отличаются друг от друга, научились создавать такие структуры и извлекать из них данные с помощью индексов и условий.
Вы попробовали считывать и сохранять датасеты в форматах CSV, Excel и JSON, освоили сортировку, группировку и агрегацию — а также построили свою первую визуализацию с помощью matplotlib.
Вы также увидели, как pandas интегрируется с другими библиотеками Python, расширяя возможности анализа и обработки реальных данных.
В следующей статье мы перейдём к важному практическому навыку — работе с HTTP-запросами и API. Вы узнаете, как загружать данные из внешних сервисов, отправлять запросы и получать ответы, а также взаимодействовать с API-сервисами вроде Static API и Яндекс Диска. Всё это — ключ к тому, чтобы ваши программы могли общаться с внешним миром.
Ключевые выводы статьи
- В
pandasопределены два основных типа объектов:Series(одномерные структуры) иDataFrame(таблицы), основанные на numpy.- Объекты
SeriesиDataFrameпозволяют фильтровать, сортировать и агрегировать данные по условиям, индексам и значениям.- С
pandasудобно считывать и сохранять данные в популярных форматах — CSV, Excel, JSON — и обрабатывать их с помощью встроенных методов.- Для анализа доступны мощные инструменты группировки (
groupby), агрегации (agg) и построения новых столбцов (assign).- Визуализация данных осуществляется с помощью библиотеки
matplotlib, на основе которой можно строить гистограммы и другие графики.