Библиотека pandas
Contents
Библиотека pandas
#
pandas (panel data) — самая популярная библиотека для работы с таблицами в python
. pandas
— сторонняя библиотека, а значит требует дополнительной установки в общем случае, но входит в дистрибутив anaconda
.
conda install pandas
или
python -m pip install pandas
При импортировании pandas
часто пользуются псевдонимом pd
.
import pandas as pd
Tip
Базовый туториал по работе с библиотекой от разработчиков можно найти здесь.
Удобную шпаргалку по pandas
можно найти здесь.
Основные объекты pandas
#
Своё название библиотека pandas
берет от английского термина panel data (панельные данные). Своим названием pandas
подсказывает то, как табличные данные представляются в ней. Дело в том, что в pandas
существует асимметрия относительно строк и столбцов: чтобы таблицы в pandas
работали эффективно, необходимо чтобы в столбцах этой таблицы были данные одинакового типа. В случае панельных данных, такой эффект достигается естественным образом, если поставить в соответствие каждой измеряемой величине столбец, а ось времени отложить вместе со строками.
В pandas
есть два основных типа объекта: DataFrame
— соответствует таблице, Series
— соответствует одному столбцу таблицы, но может существовать и сам по себе.
DataFrame
#
DataFrame — двумерная структура данных, которая может хранить данные разных типов в столбцах.
Больше всего DataFrame
напоминает лист (SpreadSheet
) из Excel
таблицы или SQL
таблицу. Объекты DataFrame
изменяемы, но с некоторыми ограничениями. Можно изменять значения в ячейках таблицы, добавлять новые столбцы на месте, но для добавления строк придется создать новый объект. Ниже приведен пример таблицы pandas
, созданной из python
словаря.
import pandas as pd
# Создание таблицы из словаря.
# Ключи словаря используются в качестве названий столбцов
# Значения используются в качестве содержимого таблицы
df = pd.DataFrame(
{
"Name": ["Ivan","Alex","Jane"],
"Age": [22, 35, 58],
"Sex": ["male", "male", "female"],
}
)
df
Name | Age | Sex | |
---|---|---|---|
0 | Ivan | 22 | male |
1 | Alex | 35 | male |
2 | Jane | 58 | female |
Series
#
Каждый столбец DataFrame
— Series.
Код в ячейке ниже демонстрирует, что созданный ранее DataFrame
состоит из трех Series
, каждый из которых соответствует одному из столбцов таблицы.
for column_name in df:
print(f"{column_name=}: {type(df[column_name])}")
print(df[column_name])
print("-" * 80)
column_name='Name': <class 'pandas.core.series.Series'>
0 Ivan
1 Alex
2 Jane
Name: Name, dtype: object
--------------------------------------------------------------------------------
column_name='Age': <class 'pandas.core.series.Series'>
0 22
1 35
2 58
Name: Age, dtype: int64
--------------------------------------------------------------------------------
column_name='Sex': <class 'pandas.core.series.Series'>
0 male
1 male
2 female
Name: Sex, dtype: object
--------------------------------------------------------------------------------
Тип данных может отличаться в разных столбцах DataFrame
объекта (таблицы), но должен быть одинаковым для всех значений Series
объекта (столбца).
Объект pandas.Series
может существовать и вне таблицы (DataFrame
). В целом он похож на одномерный numpy.ndarray
, но имеет расширенный индекс. Ниже приводится пример создания pd.Series
из списка целых чисел, которому в качестве индекса присваиваются строки.
# Создание pd.Series из списка
# В качестве индекса указывается массив строк
age = pd.Series(
[22, 35, 58],
index=["Ivan", "Alex", "Jane"]
)
age
Ivan 22
Alex 35
Jane 58
dtype: int64
Особенности индексирования в pandas
#
Главным отличием от массивов NumPy
заключается в том, что объекты в pandas
индексированы специальным объектом pd.index. Благодаря этому таблицы и столбцы можно удобно и эффективно индексировать не только целочисленным смещением, как в NumPy
, но и строковыми значениями, датами, временными рядами и любыми другими хэшируемыми объектами. В ячейке ниже приводится пример такого индексирования: первое значение 22 столбца age
имеет нулевое смещение от начала и записано под меткой "Ivan"
, что позволяет получить это значение и по метке "Ivan"
и по 0 индексу.
print(f"{age.iloc[0]=}")
print(f"{age.loc['Ivan']=}")
age.iloc[0]=22
age.loc['Ivan']=22
В этом отношении объекты pandas
похожи на словари, так как они позволяют быстрый доступ к данным по индексу (как бы ключу), но в отличие от словарей
индекс может повторяться для разных строк таблицы/столбца (у словарей ключи уникальны);
объекты
pandas
упорядочены, т.е. являются последовательностями и их элементы пронумерованы (словари не являются последовательностями).
Кроме этого такая индексация позволяет без особых усилий со стороны программиста выравнивать данные из разных источников. Чтобы проиллюстрировать это, создадим несколько столбцов, иллюстрирующих оценки группы студентов по разным дисциплинам.
math = pd.Series({
"Иванов": 5,
"Петров": 3,
"Сидоров": 4,
"Фадеев": 2
}, name="Математика", dtype=pd.Int8Dtype)
physics = pd.Series({
"Сидоров": 5,
"Иванов": 3,
"Петров": 4
}, name="Физика", dtype=pd.Int8Dtype)
chemistry = pd.Series({
"Петров": 5,
"Сидоров": 3,
"Иванов": 4
}, name="Химия", dtype=pd.Int8Dtype)
for discipline in (math, physics, chemistry):
print(discipline)
print("_"*80)
Иванов 5
Петров 3
Сидоров 4
Фадеев 2
Name: Математика, dtype: object
________________________________________________________________________________
Сидоров 5
Иванов 3
Петров 4
Name: Физика, dtype: object
________________________________________________________________________________
Петров 5
Сидоров 3
Иванов 4
Name: Химия, dtype: object
________________________________________________________________________________
Заметьте, что в каждом из столбцов студенты перечислены в разном порядке, а также студент “Фадеев” явился только на первый экзамен по математике, а остальные пропустил. Свести все эти столбцы в единую таблицу pandas
очень легко именно из-за индекса.
grades = pd.DataFrame({
"Математика": math,
"Физика": physics,
"Химия": chemistry
})
grades
Математика | Физика | Химия | |
---|---|---|---|
Иванов | 5 | 3 | 4 |
Петров | 3 | 4 | 5 |
Сидоров | 4 | 5 | 3 |
Фадеев | 2 | NaN | NaN |
За счет применения индекса при создании столбцов math
, physics
и chemistry
библиотека pandas
сама разобралась с выравниванием значений этих столбцов. Т.к. только в одном из столбцов присутствовала оценка по метке "Фадеев"
, то библиотека pandas
интерпретировало это так, будто бы в остальных столбцах значение по этой метке пропущено, что в pandas
моделируется значением NaN
.
Ещё индексы могут быть многоуровневыми, что позволяет в ряде случаев элегантно представлять в табличном виде многомерные данные.
from itertools import product
grades = pd.DataFrame({
"Математика": [5, 4, 5, 5, 4, 4],
"Физика": [4, 5, 4, 4, 5, 5],
"Химия": [5, 5, 5, 5, 5, 5]
},
index=pd.MultiIndex.from_tuples(
list(product(["Иванов", "Петров", "Сидоров"], ["Осень", "Весна"])),
names=("Фамилия", "Семестр")
)
)
grades
Математика | Физика | Химия | ||
---|---|---|---|---|
Фамилия | Семестр | |||
Иванов | Осень | 5 | 4 | 5 |
Весна | 4 | 5 | 5 | |
Петров | Осень | 5 | 4 | 5 |
Весна | 5 | 4 | 5 | |
Сидоров | Осень | 4 | 5 | 5 |
Весна | 4 | 5 | 5 |
Ниже выводятся индексы созданных ранее объектов pandas
.
Индекс таблицы сгенерировался автоматически, т.к. не был явно указан при создании. В таком случае всегда генерируется RangeIndex
, который в точности соответствует обычному индексу смещения относительно начала.
df.index
RangeIndex(start=0, stop=3, step=1)
Индекс столбца Age
соответствует переданному при создании списку имён.
age.index
Index(['Ivan', 'Alex', 'Jane'], dtype='object')