Pandas для начинающих: DataFrame за 15 минут
Библиотека pandas в Python с нуля: установка, Series и DataFrame, чтение CSV и Excel, выборка loc/iloc, фильтрация, groupby, merge и сохранение результата.
Содержание · 15 разделов
- Установка pandas
- Series и DataFrame: две главные структуры
- Чтение CSV и Excel
- Первый взгляд на данные: head, info, describe
- Выборка: столбцы, loc и iloc
- Фильтрация строк
- Сортировка
- Пропущенные значения
- Новые столбцы
- Группировка: groupby и агрегаты
- Объединение таблиц: merge и concat
- Сохранение результата: to_csv и to_excel
- Частые ошибки
- KeyError: ‘название столбца’
- Все данные в одном столбце
- UnicodeDecodeError при чтении CSV
- Изменение не сохранилось в DataFrame
- ModuleNotFoundError: No module named ‘pandas’
- Частые вопросы
- Как показать все столбцы и строки DataFrame?
- Что значит ParserError: Error tokenizing data?
- Как прочитать числа с запятой и пробелами вроде «1 200,50»?
- Как удалить дубликаты строк?
- Как загрузить в DataFrame данные из базы SQL?
- Нужен ли pyarrow для pandas 3.0?
- Итог
Pandas — библиотека Python для работы с таблицами: она читает CSV и Excel, фильтрует, группирует и считает данные, а затем сохраняет результат обратно в файл. Короткий ответ, с чего начать:
import pandas as pd
df = pd.read_csv("sales.csv") # прочитать таблицу
print(df.head()) # первые 5 строк
print(df.groupby("city")["price"].sum()) # сумма по городам
Ниже — всё, что нужно для первой реальной задачи с pandas в Python: от установки до отчёта в Excel. Примеры проверены на pandas 3.0 и Python 3.12; почти всё работает и в pandas 2.x — отличия отмечены отдельно.
Установка pandas
Pandas не входит в стандартную библиотеку, его ставят через pip. Лучше делать это в виртуальном окружении проекта:
# Windows
py -m pip install pandas openpyxl
# macOS / Linux
python3 -m pip install pandas openpyxl
openpyxl нужен для чтения и записи файлов .xlsx — без него read_excel() и to_excel() завершатся с ImportError. Подробнее об установке пакетов — в статьях про pip и установку библиотек Python.
Проверка:
import pandas as pd
print(pd.__version__) # → 3.0.6 (у вас может быть другая версия)
Сокращение pd — общепринятое соглашение, его используют документация и почти все примеры в интернете.
Series и DataFrame: две главные структуры
Series — одномерный массив с подписями (индексом). Это один столбец таблицы:
s = pd.Series([10, 20, 30], index=["a", "b", "c"], name="score")
print(s["b"]) # → 20
print(s.mean()) # → 20.0
DataFrame — таблица из нескольких Series с общим индексом. Её удобно создать из словаря, где ключи — названия столбцов:
df = pd.DataFrame({
"name": ["Анна", "Борис", "Вера"],
"age": [28, 35, 22],
"city": ["Москва", "Казань", "Москва"],
})
print(df)
# name age city
# 0 Анна 28 Москва
# 1 Борис 35 Казань
# 2 Вера 22 Москва
print(df.shape) # → (3, 3) — строки и столбцы
print(list(df.columns)) # → ['name', 'age', 'city']
Числа слева (0, 1, 2) — это индекс. По умолчанию он числовой, но индексом может быть и столбец с датами или идентификаторами.
Чтение CSV и Excel
Дальше все примеры используют файл sales.csv:
date,city,product,qty,price
2026-01-05,Москва,Ноутбук,2,85000
2026-01-05,Казань,Мышь,10,900
2026-01-06,Москва,Монитор,3,21000
2026-01-07,Пермь,Ноутбук,1,82000
2026-01-07,Казань,Монитор,,20500
2026-01-08,Москва,Мышь,15,850
df = pd.read_csv("sales.csv", parse_dates=["date"])
parse_dates сразу превращает столбец в даты. Полезные параметры read_csv():
| Параметр | Зачем |
|---|---|
sep=";" | разделитель не запятая (типично для русского Excel) |
encoding="cp1251" | файл сохранён не в UTF-8 |
usecols=["city", "price"] | прочитать только нужные столбцы |
nrows=1000 | прочитать первые N строк — для проверки большого файла |
index_col="date" | сделать столбец индексом |
dtype={"inn": str} | задать тип столбца (например, не терять ведущие нули) |
Excel-файлы читаются так же просто (нужен openpyxl):
df = pd.read_excel("report.xlsx", sheet_name="Продажи")
sheets = pd.read_excel("report.xlsx", sheet_name=None) # словарь {имя листа: DataFrame}
Первый взгляд на данные: head, info, describe
df.head(3) # первые 3 строки (по умолчанию 5)
df.tail(2) # последние 2 строки
df.info() # столбцы, типы, количество непустых значений
RangeIndex: 6 entries, 0 to 5
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 6 non-null datetime64[us]
1 city 6 non-null str
2 product 6 non-null str
3 qty 5 non-null float64
4 price 6 non-null int64
Уже здесь видно, что в qty одно пропущенное значение — поэтому столбец стал float64, а не целым. В pandas 2.x вывод отличается двумя типами: строковые столбцы там object, а даты — datetime64[ns]. В pandas 3.0 строки получают отдельный тип str, а даты из текста по умолчанию читаются с точностью до микросекунд (datetime64[us]).
describe() выводит статистику по числовым столбцам: количество, среднее, стандартное отклонение, минимум, квартили и максимум. Для текстовых столбцов полезен value_counts():
print(df["city"].value_counts())
# city
# Москва 3
# Казань 2
# Пермь 1
Выборка: столбцы, loc и iloc
df["city"] # один столбец → Series
df[["city", "price"]] # несколько столбцов → DataFrame (двойные скобки!)
Для строк есть два индексатора:
loc— по меткам: значениям индекса и названиям столбцов;iloc— по позициям: номерам строк и столбцов, как в списке.
df.loc[0, "product"] # → 'Ноутбук'
df.loc[0:2, ["city", "qty"]] # строки с метками 0..2 включительно
df.iloc[0] # первая строка целиком
df.iloc[:2, :3] # первые 2 строки и первые 3 столбца
Обратите внимание: срез в loc включает правую границу, а в iloc — нет, как в обычных списках Python.
Фильтрация строк
Условие над столбцом даёт Series из True/False, а её можно подставить в квадратные скобки:
df[df["price"] > 20000]
# Несколько условий: & (и), | (или), ~ (не); каждое условие — в скобках
df[(df["city"] == "Москва") & (df["price"] > 10000)]
# Значение из списка
df[df["city"].isin(["Казань", "Пермь"])]
# Поиск подстроки
df[df["product"].str.contains("Мон")]
# То же условие строкой
df.query("price > 20000 and city == 'Москва'")
Фильтр и выбор столбцов удобно совмещать в loc:
df.loc[df["city"] == "Москва", ["product", "qty"]]
# product qty
# 0 Ноутбук 2.0
# 2 Монитор 3.0
# 5 Мышь 15.0
Сортировка
df.sort_values("price", ascending=False).head(3) # три самые дорогие позиции
df.sort_values(["city", "price"], ascending=[True, False]) # по городу, внутри — по цене
df.sort_index() # по индексу
Методы pandas по умолчанию возвращают новый DataFrame и не меняют исходный. Результат нужно присвоить: df = df.sort_values("price").
Пропущенные значения
Пустые ячейки pandas хранит как NaN:
print(df.isna().sum()) # сколько пропусков в каждом столбце
# qty 1, остальные 0
df.dropna(subset=["qty"]) # удалить строки, где qty пусто
df["qty"] = df["qty"].fillna(0).astype(int) # заменить пропуски нулём и сделать целым
Вместо нуля пропуск можно заполнить средним: df["qty"].fillna(df["qty"].mean()). Что выбрать — зависит от смысла данных, универсального ответа нет.
Новые столбцы
Арифметика над столбцами выполняется сразу для всех строк — цикл не нужен:
df["total"] = df["qty"] * df["price"]
df["is_big"] = df["total"] > 100000
df["month"] = df["date"].dt.month # часть даты через .dt
df["city_code"] = df["city"].map({"Москва": "MSK", "Казань": "KZN", "Пермь": "PRM"})
df = df.rename(columns={"qty": "quantity"})
df = df.drop(columns=["is_big"])
Для строк есть аксессор .str (df["city"].str.upper()), для дат — .dt. Метод apply() с функцией тоже работает, но он медленнее векторных операций — используйте его, когда без него не обойтись.
Группировка: groupby и агрегаты
groupby() разбивает таблицу на группы и считает по каждой итог — аналог GROUP BY в SQL и сводных таблиц Excel:
df.groupby("city")["total"].sum()
# city
# Казань 9000
# Москва 245750
# Пермь 82000
Несколько показателей сразу — через agg() с именованными агрегатами:
report = df.groupby("city").agg(
orders=("product", "count"),
revenue=("total", "sum"),
avg_price=("price", "mean"),
)
# orders revenue avg_price
# city
# Казань 2 9000 10700.000000
# Москва 3 245750 35616.666667
# Пермь 1 82000 82000.000000
Группировать можно по нескольким столбцам: df.groupby(["city", "product"])["quantity"].sum().reset_index(). reset_index() превращает группы обратно в обычные столбцы. Сводная таблица в стиле Excel строится через pivot_table():
df.pivot_table(index="city", columns="product", values="total", aggfunc="sum", fill_value=0)
Объединение таблиц: merge и concat
merge() соединяет две таблицы по ключу — как JOIN в SQL:
regions = pd.DataFrame({
"city": ["Москва", "Казань", "Пермь"],
"region": ["ЦФО", "ПФО", "ПФО"],
})
merged = df.merge(regions, on="city", how="left")
Параметр how задаёт тип соединения: "left", "right", "inner" (по умолчанию) или "outer". Если ключи называются по-разному, используйте left_on= и right_on=.
pd.concat([df1, df2]) просто склеивает таблицы с одинаковыми столбцами одну под другой — например, выгрузки за разные месяцы.
Сохранение результата: to_csv и to_excel
df.to_csv("result.csv", index=False, encoding="utf-8-sig")
df.to_excel("result.xlsx", index=False, sheet_name="Продажи")
index=False— не записывать числовой индекс отдельным столбцом;encoding="utf-8-sig"— чтобы Excel на Windows корректно показал кириллицу в CSV.
Несколько листов в одном файле:
with pd.ExcelWriter("report.xlsx") as writer:
df.to_excel(writer, sheet_name="Данные", index=False)
report.to_excel(writer, sheet_name="Итоги")
Частые ошибки
KeyError: ‘название столбца’
Столбца с таким именем нет. Проверьте df.columns: часто в названии лишний пробел или другой регистр. Пробелы убирает df.columns = df.columns.str.strip().
Все данные в одном столбце
CSV сохранён с разделителем ;, а pandas по умолчанию ждёт запятую. Укажите sep=";".
UnicodeDecodeError при чтении CSV
Файл не в UTF-8 — обычно это выгрузка из старых программ под Windows. Попробуйте encoding="cp1251".
Изменение не сохранилось в DataFrame
Цепочка вида df["price"][0] = 1 (chained assignment) в pandas 3.0 никогда не меняет исходную таблицу: промежуточный результат ведёт себя как копия, а pandas выдаёт предупреждение ChainedAssignmentError. В pandas 2.x итог зависел от операции, и о риске предупреждал SettingWithCopyWarning. Присваивайте за один шаг через loc:
df.loc[df["city"] == "Москва", "price"] = 0
Та же причина у «пропавших» результатов sort_values(), dropna(), rename(): они возвращают новый объект, который нужно присвоить.
ModuleNotFoundError: No module named ‘pandas’
Pandas установлен в другой интерпретатор или окружение. Ставьте его командой python -m pip install pandas тем же Python, которым запускаете скрипт. Подробный разбор — в статье про ModuleNotFoundError.
Частые вопросы
Как показать все столбцы и строки DataFrame?
При печати большой таблицы pandas скрывает середину за многоточием. Лимиты снимаются настройками отображения:
pd.set_option("display.max_columns", None) # все столбцы
pd.set_option("display.max_rows", 200) # до 200 строк вместо 60 по умолчанию
pd.set_option("display.width", None) # ширина по размеру терминала
Снимать лимит строк полностью (None) на таблицах в сотни тысяч строк не стоит — вывод займёт весь терминал. Для просмотра выборочно используйте head(), tail() и sample().
Что значит ParserError: Error tokenizing data?
pandas.errors.ParserError: Error tokenizing data. C error: Expected 2 fields in line 3, saw 4
В строке 3 файла больше разделителей, чем в заголовке. Обычно неверно указан sep (например, ; внутри данных при запятой по умолчанию) или в тексте есть неэкранированные кавычки. Проверьте разделитель, а битые строки при необходимости пропустите параметром on_bad_lines="skip".
Как прочитать числа с запятой и пробелами вроде «1 200,50»?
Укажите десятичный разделитель и разделитель тысяч — тогда столбец сразу станет числовым:
df = pd.read_csv("ru.csv", sep=";", decimal=",", thousands=" ")
print(df["Сумма"].sum()) # → 2180.5
Если в выгрузке из Excel вместо обычного пробела неразрывный, передайте thousands="\xa0".
Как удалить дубликаты строк?
drop_duplicates() оставляет первую из одинаковых строк. Параметр subset сравнивает только выбранные столбцы, keep="last" оставляет последнее вхождение:
df = df.drop_duplicates()
df = df.drop_duplicates(subset=["city"], keep="last") # одна строка на город
Как загрузить в DataFrame данные из базы SQL?
pd.read_sql() принимает SQL-запрос и подключение. Для SQLite хватит модуля sqlite3, для PostgreSQL и MySQL обычно передают движок SQLAlchemy:
import sqlite3
conn = sqlite3.connect("library.db")
books = pd.read_sql("SELECT title, year FROM books WHERE year < ?", conn, params=(1850,))
Обратная операция — df.to_sql("books", conn, if_exists="append", index=False). Подробнее о работе с базами — в статье про SQLAlchemy.
Нужен ли pyarrow для pandas 3.0?
Нет, pyarrow — необязательная зависимость. Если он установлен, строковый тип str хранит данные в формате Apache Arrow, это экономит память и ускоряет операции со строками; без него pandas использует обычное хранение. Для форматов Parquet и Feather pyarrow нужен: pip install pyarrow.
Итог
Для большинства задач хватает десятка приёмов: read_csv/read_excel, head и info, фильтрация через loc, groupby().agg(), merge и to_excel. Полный справочник — в официальной документации pandas. Другие инструменты для данных, сети и графики собраны в обзоре библиотек Python, а загрузить данные из веб-API поможет библиотека requests.
- #Python
- #pandas
- #DataFrame
- #Анализ данных
- #Excel
- #CSV