Перейти к основному содержимому

Pandas — типовые операции


Основы табличных данных на Python

Pandas — главная библиотека Python для работы с таблицами: как Excel или Google Таблицы, но в коде. Её используют в школе (средний балл класса, частоты ответов опроса), в вузе (лабораторные по статистике, курсовые по данным) и на работе (отчёты, аналитика, подготовка данных для машинного обучения).

С чего начать

Массивы и матрицы — примеры NumPy (идут перед Pandas). Теория и обзор экосистемы — Анализ данных и научные вычисления. Шпаргалка команд — типовые операции Pandas. Тот же смысл в таблице без кода — Pandas, Polars, SQL и Excel. Если Pandas ещё рано — Python — файлы и текст (CSV через csv) или формулы Excel и Google Sheets (СУММ, groupby ≈ сводная, merge ≈ ВПР). Графики — Matplotlib, примеры. Символьная математика — SymPy — уравнения и производные. Здесь — готовые скрипты с разбором каждой строки.

Частые запросы в Google — куда смотреть

Ищут в интернетеРаздел ниже
pandas read csv примерЗагрузка CSV
pandas filter rows by conditionФильтрация строк
pandas groupby sum meangroupby
pandas dropna fillnaОчистка
pandas merge two dataframesmerge
pandas pivot table examplepivot_table
pandas среднее по столбцуОбязательные элементы
pandas value_countsЧастоты
pandas to_csvЭкспорт

Как запустить пример

  1. Установите библиотеки (один раз в терминале или командной строке):
pip install pandas

Разбор:

  • pip — установщик пакетов Python; идёт вместе с Python на Windows и macOS.
  • pandas — сама библиотека; после установки доступен import pandas as pd в любом скрипте.
  • Для чтения Excel дополнительно: pip install openpyxl.
  1. Скопируйте код в файл, например analiz.py.
  2. Запустите: python analiz.py — результат появится в терминале (чёрное окно).
  3. В Google Colab (colab.research.google.com) или Jupyter Notebook выполняйте код по ячейкам; таблица отображается прямо под ячейкой — print() для таблицы не обязателен.
Кому подойдёт эта страница

Школьникам — средний балл по классу, топ учеников, сколько пятёрок и четвёрок.
Студентам — groupby, merge, pivot для лабораторных по статистике и информатике.
Начинающим аналитикам — шаблон «загрузил CSV → почистил → посчитал → сохранил отчёт» без лишней теории.


Базовые термины

ТерминПростыми словамиАналог в Excel
DataFrameТаблица: строки и именованные столбцыЛист целиком
SeriesОдин столбец (или одна строка) с меткамиОдин столбец A, B, C…
indexМетки строк слева (0, 1, 2 … или свои имена)Номера строк
NaNПропущенное значение («пустая ячейка»)Пустая ячейка
locВыбор по имени строки и столбцаФильтр по подписи
ilocВыбор по номеру (как в списке Python)«Строка 3, столбец 2»
groupbyГруппировка и сумма/среднее по категориямСводная таблица → группировка
mergeСклейка двух таблиц по ключуВПР (VLOOKUP) или JOIN

Какую операцию выбрать

ЗадачаЧто использоватьПример одной строки
Первый взгляд на таблицуhead, info, describedf.head()
Отобрать строки по условиюбулев фильтр в []df[df["score"] >= 4]
Среднее по группамgroupby + aggdf.groupby("city")["amount"].sum()
Убрать пустые ячейкиdropna, fillnadf.dropna()
Склеить заказы и клиентовmergeorders.merge(users, on="user_id")
Свод как в Excelpivot_tabledf.pivot_table(...)
Сохранить результатto_csvdf.to_csv("report.csv", index=False)

Обязательные элементы

Любой скрипт с Pandas строится по схеме: импорт → таблица → осмотр → операция → результат. Это минимальный каркас — как import turtle и turtle.done() в графике черепахой.

import pandas as pd

# 1. Таблица (из словаря, CSV или Excel)
df = pd.DataFrame({
"name": ["Аня", "Боря", "Вера"],
"score": [5, 4, 5],
})

# 2. Осмотр — что вообще загрузилось
print(df.head())
print(df.describe())

# 3. Операция (пример — средний балл класса)
print("Средний балл:", df["score"].mean())

Разбор:

  • import pandas as pd — подключаем библиотеку; pd — общепринятое сокращение (как plt у Matplotlib). Все вызовы дальше: pd.read_csv, pd.DataFrame.
  • pd.DataFrame({...}) — создаём таблицу из словаря Python: ключи ("name", "score") становятся именами столбцов, списки — значениями по строкам. Первая строка таблицы: Аня, 5; вторая: Боря, 4.
  • df — переменная, в которой лежит таблица; имя df (data frame) используют почти везде в учебниках.
  • df.head() — показать первые 5 строк; после загрузки большого CSV это первое, что делают, чтобы убедиться, что файл прочитался правильно.
  • df.describe() — автоматическая сводка по числовым столбцам: сколько значений, среднее, минимум, максимум, квартили. Для столбца score увидите mean ≈ 4.67.
  • df["score"] — взять один столбец; квадратные скобки с именем — как в Excel «столбец C».
  • .mean()среднее арифметическое по всему столбцу; без цикла for по строкам. Аналоги: .sum(), .max(), .min(), .median().
  • print(...) — вывести текст в консоль; в Jupyter можно просто написать df.head() в последней строке ячейки.

Школьный вариант: замените имена и оценки на свой класс — (5+4+5)/3 посчитает Python сам. Добавьте ученика: допишите "Коля" в name и 3 в score.

Типичные ошибки новичков
  • df[df["a"] > 0 and df["b"] == "x"] — ошибка. В Pandas для «и» нужен &: df[(df["a"] > 0) & (df["b"] == "x")]. Слово and работает с одним True/False, а не с целым столбцом.
  • После фильтра subset = df[mask] и правка subset["col"] = 1 — жёлтое SettingWithCopyWarning. Пишите subset = df[mask].copy().
  • Даты в CSV как текст "2024-01-05"resample не работает, пока не вызовете pd.to_datetime(df["date"]).
  • ID 00123 превращается в 123 — в read_csv укажите dtype={"id": str}.

Стартовые операции

Пять блоков, которые чаще всего нужны в первой лабораторной по данным: осмотр → фильтр → группировка → очистка → сохранение. Каждый блок — отдельный маленький скрипт, который можно скопировать целиком.


Создание таблицы и первый осмотр

Зачем: прежде чем считать среднее или строить график, нужно понять, что в файле — сколько строк, есть ли пустые ячейки, не перепутались ли типы (число vs текст). Это называют EDA (exploratory data analysis) — разведка данных.

import pandas as pd

df = pd.DataFrame({
"city": ["Москва", "Казань", "Москва", "Сочи"],
"product": ["A", "B", "A", "C"],
"amount": [1200, 800, None, 1500],
"qty": [2, 1, 3, 2],
})

print("Первые строки:\n", df.head(3))
print("\nСтруктура:\n")
df.info()
print("\nСтатистика:\n", df.describe())
print("\nПропуски по столбцам:\n", df.isnull().sum())

Разбор:

  • pd.DataFrame({...}) — учебная таблица «продажи по городам»; в реальной работе вместо неё будет df = pd.read_csv("sales.csv").
  • "city": ["Москва", ...] — столбец городов; четыре строки в каждом списке → четыре строки в таблице.
  • None в amountпропуск; Pandas сохранит его как NaN (Not a Number). Так выглядят пустые ячейки в CSV.
  • df.head(3) — только 3 верхние строки; аргумент 3 ограничивает вывод. Без аргумента — 5 строк.
  • df.info()технический паспорт таблицы: число строк (4), число столбцов (4), тип каждого столбца (object = текст, float64 = число с дробной частью), сколько непустых значений в amount (3 из 4 — одна дыра).
  • describe() — статистика только для чисел (amount, qty): среднее, std, min, max. Текстовые city и product сюда не попадают.
  • isnull() — для каждой ячейки True, если пусто; .sum() складывает True как 1 по столбцам → видно, что в amount один пропуск.

Что увидите в консоли: таблицу из 3 строк, строку amount 1 в блоке пропусков — сигнал почистить данные перед суммированием.


Фильтрация строк

Зачем: оставить только нужные записи — «все с оценкой 4 и выше», «только 10А», «только Москва». В Excel это автофильтр; в Pandas — условие в квадратных скобках.

import pandas as pd

df = pd.DataFrame({
"name": ["Аня", "Боря", "Вера", "Глеб"],
"class": ["10А", "10Б", "10А", "10Б"],
"score": [5, 3, 4, 5],
})

top = df[df["score"] >= 4]
class_10a = df[df["class"] == "10А"]
both = df[(df["class"] == "10А") & (df["score"] == 5)]
by_list = df[df["name"].isin(["Аня", "Глеб"])]

print("Оценка 4 и выше:\n", top)
print("\n10А с пятёркой:\n", both)

Разбор:

  • df["score"] >= 4не одно True/False, а столбец: [True, False, True, True] для оценок 5, 3, 4, 5. Pandas сравнивает весь столбец сразу — это быстрее цикла for.
  • df[...] с таким столбцом внутри — маска: остаются только строки, где True. В top попадут Аня, Вера, Глеб.
  • == — сравнение «равно»; один знак = — это присваивание (x = 5), частая опечатка новичков.
  • (df["class"] == "10А") & (df["score"] == 5)два условия сразу; оператор & — «и» для таблиц. Скобки обязательны: без них Python сначала выполнит & не там.
  • Почему не and? Python and берёт одно значение слева и справа; Series — целый столбец, отсюда ошибка ValueError.
  • isin(["Аня", "Глеб"]) — «имя в списке»; то же, что SQL WHERE name IN ('Аня', 'Глеб').
  • class_10a и bothновые таблицы; исходный df не меняется, пока вы не пишете df = df[...].

Школьный вариант: top — список отличников; both — только пятёрки в 10А (одна строка: Аня).

Альтернатива: df.query("score >= 4 and class == '10А'") — тот же смысл, синтаксис ближе к SQL; удобно, когда условий много.


groupby — статистика по группам

Зачем: ответ на вопрос «сколько всего / в среднем по каждому городу, классу, месяцу?». Одна строка кода вместо ручного разбиения таблицы на куски.

import pandas as pd

sales = pd.DataFrame({
"city": ["Москва", "Казань", "Москва", "Казань", "Сочи"],
"amount": [100, 50, 120, 80, 200],
})

by_city = sales.groupby("city")["amount"].agg(["sum", "mean", "count"])
by_city_sorted = by_city.sort_values("sum", ascending=False)

print(by_city)
print("\nТоп по выручке:\n", by_city_sorted.head(2))

Разбор:

  • sales — пять отдельных продаж; Москва встречается дважды (100 и 120), Казань — дважды (50 и 80).
  • groupby("city")сложить в кучки все строки с одинаковым городом. Внутри получаются три группы: Москва (2 строки), Казань (2), Сочи (1).
  • ["amount"] — считаем статистику только по столбцу суммы; без этого agg попытается обработать и city (текст).
  • .agg(["sum", "mean", "count"]) — три функции за один проход: sum — сумма (Москва: 220), mean — средний чек (Москва: 110), count — сколько строк (2).
  • Результат by_cityновая таблица: индекс = название города, столбцы = sum, mean, count.
  • sort_values("sum", ascending=False) — сортировка по сумме от большей к меньшей; ascending=True — наоборот.
  • .head(2) — две верхние строки после сортировки → топ-2 города по выручке.

Школьный вариант: замените на "class" и "score" — получите сумму и средний балл по каждому классу.

Одна функция: достаточно sales.groupby("city")["amount"].sum() — без agg, если нужна только сумма.


Очистка — пропуски и дубликаты

Зачем: реальные данные с опросов и Excel «грязные» — лишние пробелы, пустые ячейки, одна анкета дважды. Перед отчётом их нормализуют, иначе среднее и графики будут неверными.

import pandas as pd
import numpy as np

df = pd.DataFrame({
"id": [1, 2, 2, 3],
"name": [" Аня ", "Боря", None, "Вера"],
"score": [5, 4, 4, np.nan],
})

df["name"] = df["name"].str.strip()
df["score"] = df["score"].fillna(df["score"].median())
df = df.drop_duplicates(subset=["id"], keep="first")
df = df.dropna(subset=["name"])

print(df)

Разбор:

  • import numpy as npnp.nan — ещё один способ обозначить пустое число; в CSV Pandas сам подставляет NaN.
  • " Аня " — пробелы по краям; в Excel так часто копируют из Word. .str.strip() убирает их у всех строк столбца сразу.
  • .strстроковые методы для целого столбца; без .str у обычного текста Python нет .strip() на Series.
  • fillna(df["score"].median()) — пустую оценку заменяем медианой (4.0 здесь). Медиана устойчивее среднего, если есть одна «двойка» среди пятёрок.
  • drop_duplicates(subset=["id"], keep="first") — два id=2 → остаётся первая строка (Боря); вторая удаляется как дубль анкеты.
  • dropna(subset=["name"]) — выкинуть строки, где имя пустое (третья строка с None в name уйдёт, если дубль id уже убран).
  • Каждая строка перезаписывает df — типичный стиль «почистили по шагам». Можно собрать в одну цепочку (см. раздел 3).

Итог: три строки с id 1, 2, 3 — без дублей, без пустых имён, оценка 5, 4, 4.

Подробный порядок шагов — очистка и подготовка в Pandas.


value_counts и describe

Зачем: «сколько человек ответили "да"», «какая оценка встречается чаще всего» — частотный анализ для опросов и контрольных.

import pandas as pd

df = pd.DataFrame({
"grade": [5, 4, 5, 3, 5, 4, 5, 5, 4, 3],
"subject": ["math"] * 5 + ["phys"] * 5,
})

print("Частоты оценок:\n", df["grade"].value_counts())
print("\nДоли (в %):\n", (df["grade"].value_counts(normalize=True) * 100).round(1))
print("\nПо предметам:\n", df.groupby("subject")["grade"].mean())

Разбор:

  • "grade" — десять оценок; пятёрок больше всего — это увидит value_counts.
  • ["math"] * 5трюк Python: список из пяти слов "math"; вторые пять строк — "phys". Так задают предмет для каждой оценки.
  • value_counts()подсчёт одинаковых значений; результат отсортирован по убыванию: 5 → 5 раз, 4 → 3 раза, 3 → 2 раза.
  • normalize=True — доли от единицы (0.5 = 50%); * 100 переводит в проценты; .round(1) — один знак после запятой для красивого вывода.
  • groupby("subject")["grade"].mean()средний балл отдельно по математике и физике; две строки в ответе.

Школьный вариант: подставьте оценки своего класса — получите «мода» (самая частая оценка) из первой строки value_counts().


Новый столбец и сортировка

Зачем: посчитать выручку (цена × количество), BMI, процент — новый столбец из существующих без формулы в каждой строке Excel.

import pandas as pd

df = pd.DataFrame({
"product": ["Ноутбук", "Мышь", "Клавиатура", "Монитор"],
"price": [80000, 1500, 3500, 25000],
"sold": [12, 150, 80, 25],
})

df = df.assign(revenue=lambda x: x["price"] * x["sold"])
top3 = df.nlargest(3, "revenue")

print(df[["product", "revenue"]])
print("\nТоп-3 по выручке:\n", top3)

Разбор:

  • Три столбца — исходные данные магазина; выручки в таблице пока нет, её вычисляем.
  • assign(revenue=lambda x: x["price"] * x["sold"]) — добавляет столбец revenue. lambda x: — маленькая функция; x — та же таблица; умножение столбец на столбец по строкам: 80000×12, 1500×150…
  • Векторизация — Pandas умножает все строки за один вызов на C; цикл for i in range(len(df)) был бы в десятки раз медленнее на больших данных.
  • df[["product", "revenue"]]два столбца сразу; двойные скобки [[ ]] = список имён столбцов.
  • nlargest(3, "revenue")3 строки с максимальной выручкой; для минимумов — nsmallest. Удобнее, чем sort_values + head, когда нужен именно топ-N.

Школьный вариант: df.assign(total=lambda x: x["hours"] * x["rate"]) — зарплата по часам.


merge — две таблицы в одну

Зачем: заказы хранят только user_id, а имена клиентов — в другой таблице. Нужно «подтянуть» имя к каждому заказу — как ВПР в Excel или JOIN в SQL.

import pandas as pd

orders = pd.DataFrame({
"order_id": [1, 2, 3],
"user_id": [10, 10, 20],
"total": [500, 300, 1200],
})

users = pd.DataFrame({
"user_id": [10, 20, 30],
"name": ["Аня", "Боря", "Вера"],
})

result = orders.merge(users, on="user_id", how="left")
print(result)

Разбор:

  • ordersтри заказа; у первых двух один клиент (user_id=10), третий — клиент 20.
  • usersсправочник id → имя; id 30 (Вера) в заказах не участвует.
  • merge(..., on="user_id") — склеить по общему столбцу; Pandas ищет одинаковые user_id в обеих таблицах и ставит имя рядом с заказом.
  • how="left"все строки из левой таблицы (orders) сохраняются; если id нет в users, имя будет NaN. Здесь все id найдены → три строки с именами Аня, Аня, Боря.
  • how="inner" — только заказы, у которых есть клиент в справочнике (здесь то же самое).
  • how="outer" — все id из обеих таблиц; появилась бы строка с Верой без заказа (NaN в total).

Школьный вариант: orders — оценки с student_id, users — ФИО из журнала.

Углублённо — объединение таблиц в Pandas.


pivot_table — сводная таблица

Зачем: посмотреть сумму продаж в разрезе «регион × месяц» — ровно как сводная таблица в Excel (Insert → PivotTable).

import pandas as pd

df = pd.DataFrame({
"region": ["Север", "Юг", "Север", "Юг", "Север"],
"month": ["Jan", "Jan", "Feb", "Feb", "Feb"],
"sales": [100, 80, 120, 90, 110],
})

pivot = df.pivot_table(
values="sales",
index="region",
columns="month",
aggfunc="sum",
fill_value=0,
)

print(pivot)

Разбор:

  • Пять исходных строк — каждая продажа отдельно; свод схлопнет их в сетку.
  • values="sales"что класть в ячейки — числа продаж.
  • index="region"строки свода: Север, Юг.
  • columns="month"столбцы: Jan, Feb.
  • aggfunc="sum" — если несколько строк попали в одну ячейку (Север + Jan = 100), сложить. Можно "mean", "count".
  • fill_value=0 — где комбинации не было (Юг + Feb только 90, но пустых не будет), вместо NaN поставить 0 — таблица читается в отчёте.

Что получится: таблица 2×2 — Север/Юг по строкам, Jan/Feb по столбцам, в ячейках суммы.


Экспорт в CSV

Зачем: сохранить результат на диск — отправить учителю, открыть в Excel, загрузить в другую программу.

import pandas as pd

summary = pd.DataFrame({
"city": ["Москва", "Казань"],
"total": [220, 130],
})

summary.to_csv("report.csv", index=False, encoding="utf-8-sig")
print("Файл report.csv сохранён")

Разбор:

  • summaryитоговая маленькая таблица после groupby; так обычно экспортируют отчёты, а не сырой миллион строк.
  • to_csv("report.csv") — записать в файл report.csv в текущей папке (откуда запускали python analiz.py).
  • index=Falseне писать служебный столбец 0, 1, 2… слева; в Excel он мешает. Почти всегда ставят False для отчётов.
  • encoding="utf-8-sig" — UTF-8 с меткой BOM; Excel на Windows правильно показывает кириллицу в «Москва», «Казань». Без этого — кракозябры.
  • После запуска рядом со скриптом появится report.csv — откройте двойным щелчком.

Примеры для лабораторных

Полные сценарии «от данных до ответа на вопрос». Код самодостаточный — файл CSV на диске не нужен; для своей работы замените только источник данных.


1. Загрузка CSV и быстрый EDA

Задача: прочитать таблицу из файла (или строки) и за 30 секунд понять — сколько строк, какие столбцы, есть ли пропуски.

import pandas as pd
from io import StringIO

# В реальной работе раскомментируйте:
# df = pd.read_csv("data.csv", encoding="utf-8", dtype={"id": str})

csv_text = "id,name,score\n1,Аня,5\n2,Боря,4\n3,Вера,5\n4,Глеб,3\n"
df = pd.read_csv(StringIO(csv_text))

print(df.head())
print(df.info())
print("\nОписательная статистика:\n", df.describe(include="all"))

Разбор:

  • from io import StringIO — «файл в памяти»; StringIO(csv_text) притворяется файлом с текстом внутри. Удобно для учебных примеров и тестов без диска.
  • csv_textминимальный CSV: первая строка — заголовки через запятую, дальше — данные. Так выглядит экспорт из Excel «CSV UTF-8».
  • pd.read_csv(StringIO(csv_text))разбор текста в таблицу: автоматически определяет заголовок, типы, запятую как разделитель.
  • В реальном проекте: pd.read_csv("data.csv", encoding="utf-8", dtype={"id": str}) — путь к вашему файлу; dtype не даёт столбцу id стать числом.
  • encoding="utf-8" — если в файле кириллица; при ошибке попробуйте encoding="cp1251" (старый Excel в Windows).
  • describe(include="all") — сводка и по числам, и по тексту (name): для строк покажет count, unique, top.

Чек-лист после read_csv: head() → типы в info() → пропуски isnull().sum() → только потом графики и groupby.


2. Отчёт «продажи по городам и товарам»

Задача: ответить «сколько выручки и сколько сделок по каждой паре город + товар» — типичный вопрос в лабораторной по экономике или IT.

import pandas as pd

df = pd.DataFrame({
"city": ["Москва", "Казань", "Москва", "Казань", "Москва"],
"product": ["A", "A", "B", "B", "A"],
"amount": [100, 80, 120, 90, 150],
})

report = (
df.groupby(["city", "product"], as_index=False)
.agg(revenue=("amount", "sum"), orders=("amount", "count"))
.sort_values("revenue", ascending=False)
)

print(report)

Разбор:

  • Пять строк — отдельные сделки; Москва+A встречается дважды (100 и 150) → в отчёте сумма 250.
  • groupby(["city", "product"]) — группы по двум ключам одновременно: (Москва, A), (Казань, A), (Москва, B)…
  • as_index=False — город и товар остаются обычными столбцами, а не «прилипают» к индексу; так проще экспортировать в CSV и читать человеку.
  • revenue=("amount", "sum")именованный агрегат: новый столбец revenue = сумма amount в группе. Читается лучше, чем голый .sum().
  • orders=("amount", "count")число строк в группе = число заказов (не путать с sum!).
  • Скобки (...)цепочка методов на нескольких строках; выполняется сверху вниз: сгруппировали → посчитали → отсортировали.
  • sort_values("revenue", ascending=False)лидеры сверху — первой строкой будет пара с максимальной выручкой.

Для курсовой: добавьте .to_csv("report_by_city.csv", index=False) в конец цепочки.


3. Очистка «грязного» опроса

Задача: анкета с Google Forms / Excel — дубли email, «Да» и «да», пустой возраст. Привести к виду, пригодному для подсчёта процентов.

import pandas as pd
import numpy as np

raw = pd.DataFrame({
"email": ["a@mail.ru", "A@mail.ru", "b@mail.ru", None, "c@mail.ru"],
"answer": [" Да ", "да", "Нет", "Да", "нет"],
"age": [17, 17, 16, np.nan, 18],
})

clean = (
raw.dropna(subset=["email"])
.assign(
email=lambda x: x["email"].str.lower().str.strip(),
answer=lambda x: x["answer"].str.strip().str.capitalize(),
age=lambda x: x["age"].fillna(x["age"].median()),
)
.drop_duplicates(subset=["email"], keep="first")
)

print("Было строк:", len(raw), "→ стало:", len(clean))
print(clean)

Разбор:

  • raw5 ответов, но одна анкета без email, один email дважды с разным регистром (a@ и A@).
  • .dropna(subset=["email"])первый шаг: строки без email бесполезны для учёта уникальных респондентов.
  • .assign(email=lambda x: x["email"].str.lower().str.strip()) — email в нижнем регистре и без пробелов; A@mail.rua@mail.ru, совпадёт с первой строкой.
  • answer=...str.capitalize() — « Да » → «Да», «нет» → «Нет»; единый формат для value_counts.
  • age=...fillna(median()) — пропуск возраста (4-я строка) заменяем медианой 17; строка потом всё равно может уйти при dedup.
  • .drop_duplicates(subset=["email"], keep="first") — после нормализации a@mail.ru дважды → остаётся первая анкета.
  • len(raw) vs len(clean)наглядная метрика для отчёта: «из 5 сырых записей 3 валидных».

Для проекта: замените capitalize() на replace({"да": "Да", "нет": "Нет", "Да": "Да"}), если ответов больше двух.


4. Временной ряд — продажи по месяцам

Задача: есть даты и суммы по дням — нужна сумма за месяц и сглаженный тренд (скользящее среднее). Частый запрос в экономике и на практикумах по данным.

import pandas as pd

df = pd.DataFrame({
"date": ["2024-01-05", "2024-01-20", "2024-02-10", "2024-02-28"],
"sales": [100, 150, 200, 180],
})

df["date"] = pd.to_datetime(df["date"])
df = df.set_index("date")

monthly = df["sales"].resample("ME").sum()
rolling_avg = df["sales"].rolling(window=2, min_periods=1).mean()

print("По месяцам:\n", monthly)
print("\nСкользящее среднее (2 точки):\n", rolling_avg)

Разбор:

  • Даты пока строки "2024-01-05" — Pandas не знает, что это календарь, пока не скажете явно.
  • pd.to_datetime(df["date"]) — превращает в тип datetime64; можно сравнивать, резать периоды, строить график по оси времени.
  • set_index("date") — дата становится индексом строк (метки слева); resample и rolling работают только с упорядоченным временным индексом.
  • resample("ME").sum()разбить время на месяцы (ME = month end) и сложить sales в каждом: январь 100+150=250, февраль 200+180=380.
  • rolling(window=2, min_periods=1).mean()среднее по последним двум точкам; для первой точки одна — min_periods=1 не даёт NaN. Сглаживает «скачки» на графике.
  • Раньше писали resample("M"); в новых pandas предпочтительно "ME".

График: после этого блока monthly.plot(kind="bar") — см. Matplotlib — примеры.


5. Строковые столбцы — поиск и извлечение

Задача: в столбце SKU-1001 найти все SKU и вытащить номер без ручного редактирования — типичная «грязная» колонка из ERP или Excel.

import pandas as pd

df = pd.DataFrame({
"code": ["SKU-1001", "SKU-2042", "ITEM-99", "sku-3000"],
"note": [" срочно ", "обычный", None, " VIP "],
})

mask = df["code"].str.contains("SKU", case=False, na=False)
nums = df["code"].str.extract(r"(\d+)", expand=False)
df["note"] = df["note"].str.strip().str.upper()

print("Строки с SKU:\n", df[mask])
print("\nИзвлечённые номера:\n", nums)
print("\nПримечания:\n", df["note"])

Разбор:

  • str.contains("SKU", case=False)есть ли подстрока SKU в code; case=Falsesku и SKU одинаковы; na=False — пустые ячейки → False, не ломают фильтр.
  • mask — столбец True/False; df[mask]только строки, где в code есть SKU (три из четырёх; ITEM-99 отсеется).
  • str.extract(r"(\d+)")регулярное выражение: \d+ = одна или больше цифр; скобки ()группа захвата → 1001, 2042, 99, 3000 в отдельном столбце.
  • expand=False — результат Series (один столбец), а не DataFrame.
  • df["note"].str.strip().str.upper() — пробелы убраны, текст заглавными; None останется NaN — для них .str не падает.

Без RegEx: df["code"].str.split("-").str[1] — взять часть после дефиса, если формат всегда XXX-число.


6. Корреляция числовых признаков

Задача: есть ли связь «чем выше рост, тем больше вес» или «балл за тест и часы сна» — вводная статистика, корреляция Пирсона.

import pandas as pd

df = pd.DataFrame({
"height_cm": [170, 165, 180, 175, 160],
"weight_kg": [65, 58, 82, 70, 55],
"test_score": [80, 75, 88, 85, 72],
})

numeric = df.select_dtypes(include="number")
print("Матрица корреляции (Пирсон):\n", numeric.corr().round(2))

Разбор:

  • Три числовых признака по пяти людям (условная выборка класса).
  • select_dtypes(include="number")отрезать только числа; если бы был столбец name (текст), он не попал бы в corr.
  • corr() — матрица 3×3: каждая ячейка — коэффициент от −1 до 1. Диагональ всегда 1 (переменная с самой собой).
  • Близко к 1 — растут вместе (рост и вес часто так); близко к 0 — связи почти нет; −1 — одна растёт, другая падает.
  • .round(2) — два знака после запятой; иначе 0.873421… мешает читать в отчёте.

Важно: корреляция не доказывает причину; только «движутся вместе». Для графика — heatmap в 1112.


7. Цепочка методов — один пайплайн

Задача: один читаемый «конвейер» — отфильтровать → посчитать по отделам → отсортировать — без пяти промежуточных переменных.

import pandas as pd

df = pd.DataFrame({
"dept": ["IT", "HR", "IT", "Sales", "IT", "HR"],
"name": ["Аня", "Боря", "Вера", "Глеб", "Дина", "Егор"],
"salary": [120000, 90000, 130000, 110000, 125000, 85000],
})

result = (
df.query("salary >= 90000")
.groupby("dept", as_index=False)
.agg(avg_salary=("salary", "mean"), headcount=("name", "count"))
.sort_values("avg_salary", ascending=False)
)

print(result)

Разбор:

  • query("salary >= 90000") — фильтр SQL-подобным текстом; имена столбцов без кавычек; число 90000 — порог «не ниже 90k». Егор (85000) выпадет до groupby.
  • Цепочка начинается с скобки ( — перенос на новую строку без ошибки синтаксиса.
  • groupby("dept")по отделам IT, HR, Sales; в IT три человека после фильтра.
  • avg_salary=("salary", "mean") — средняя зарплата в отделе; headcount=("name", "count")сколько человек (считаем непустые name).
  • sort_values("avg_salary", ascending=False) — отдел с максимальной средней зарплатой первым.
  • В Jupyter последней строкой можно просто result — таблица отрисуется HTML.

Стиль для курсовой: комментарий над цепочкой — «Шаг 1: фильтр зарплат ≥ 90k; Шаг 2: агрегат по dept».


8. Чтение Excel и лист по имени

Задача: данные лежат в .xlsx на листе «Продажи» — прочитать и сохранить итог в новый файл.

import pandas as pd

# В проекте раскомментируйте:
# df = pd.read_excel("report.xlsx", sheet_name="Продажи", engine="openpyxl")

df = pd.DataFrame({"month": ["Jan", "Feb"], "value": [10, 15]})

df.to_excel("out.xlsx", sheet_name="Итог", index=False)
print(df)
print("\nСохранено в out.xlsx (нужен: pip install openpyxl)")

Разбор:

  • read_excel(..., sheet_name="Продажи")конкретный лист; sheet_name=0 — первый лист по номеру.
  • engine="openpyxl"движок для формата xlsx; без установленного openpyxl будет ImportError.
  • to_excel("out.xlsx", sheet_name="Итог", index=False)запись таблицы на лист «Итог»; файл создаётся или перезаписывается.
  • Excel удобен для преподавателя и бухгалтерии; для больших данных и Python-пайплайнов чаще CSV или Parquet.

Переиспользуемые шаблоны

Шаблон «загрузил → почистил → отчёт»

Зачем: обернуть повторяющиеся шаги в функцию — один раз написали, вызываете с разными файлами.

import pandas as pd

def load_and_summarize(path: str) -> pd.DataFrame:
df = pd.read_csv(path, encoding="utf-8")
df = df.dropna(how="all").drop_duplicates()
summary = df.groupby(df.columns[0], as_index=False).mean(numeric_only=True)
return summary

# summary = load_and_summarize("data.csv")
# summary.to_csv("summary.csv", index=False)

Разбор:

  • def load_and_summarize(path: str) — функция принимает путь к CSV; : str — подсказка типа (не обязательна для запуска).
  • -> pd.DataFrame — функция возвращает таблицу; можно присвоить в переменную или сразу .to_csv.
  • dropna(how="all") — удалить строки, где все ячейки пустые (мусорные строки в конце Excel).
  • drop_duplicates() — полные копии строк; без subset — сравниваются все столбцы.
  • df.columns[0]имя первого столбца; группировка «по первому полю» — универсальный черновик; лучше заменить на "region" и т.д.
  • mean(numeric_only=True) — среднее только по числам; текстовые столбцы не ломают расчёт.
  • Строки с #закомментированы; уберите #, когда будет реальный data.csv.

Шаблон для Jupyter и Colab

Зачем: в ноутбуке таблица на тысячи строк забивает экран; настроим красивый вывод один раз в начале.

import pandas as pd

pd.set_option("display.max_rows", 20)
pd.set_option("display.float_format", lambda x: f"{x:,.2f}")

df = pd.DataFrame({"a": [1.234567, 2.345678]})
df # в ноутбуке последняя строка — красивая HTML-таблица

Разбор:

  • pd.set_option(...)глобальные настройки Pandas на всю сессию ноутбука.
  • display.max_rows — показывать не больше 20 строк; остальное сворачивается в ....
  • display.float_format — числа как 1.23 с разделителем тысяч; 1234567.891,234,567.89.
  • Последняя строка ячейки df без print — в Jupyter/Colab отображается интерактивная таблица; в обычном .py нужен print(df).

См. также

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").