134 lines
9.3 KiB
Markdown
134 lines
9.3 KiB
Markdown
# Летняя практика — Турнирные таблицы КХЛ
|
||
|
||
Проект анализирует результаты матчей регулярного чемпионата КХЛ за сезоны
|
||
**2018/19 – 2021/22** и строит по ним турнирные таблицы и графики.
|
||
Основной инструмент — библиотека **pandas** (работа с таблицами) и
|
||
**matplotlib** (графики).
|
||
|
||
---
|
||
|
||
## 1. Структура проекта
|
||
|
||
| Файл / папка | Назначение |
|
||
|---|---|
|
||
| `main.py` | Основная программа: строит полную турнирную таблицу чемпионата и таблицы по конференциям (Запад / Восток). |
|
||
| `individual_1.py` | Индивидуальное задание: гистограмма набранных очков по командам. |
|
||
| `individual_4.py` | Индивидуальное задание: гистограмма всего заброшенных шайб за сезон. |
|
||
| `individual_5.py` | Индивидуальное задание: гистограмма разницы шайб конкретной команды в заданном периоде по датам. |
|
||
| `khl_3/` | Исходные данные — CSV-файлы матчей (кодировка UTF-8). |
|
||
| `khl_3_win/` | Те же данные в кодировке UTF-8 **с BOM** — открываются в Excel без «кракозябр». |
|
||
|
||
### Формат исходных данных (CSV)
|
||
|
||
```
|
||
,Номер,Дата,Команда_1,Команда_2,Период_1,Период_2,Период_3,Овертайм,Буллиты
|
||
0,1,2018-09-01,Ак Барс,СКА,0:1,1:2,0:3,:,:
|
||
```
|
||
|
||
* `Команда_1` — хозяева, `Команда_2` — гости.
|
||
* `Период_1..3`, `Овертайм`, `Буллиты` — счёт в формате `хозяева:гости`.
|
||
* Пустой `:` означает, что период не игрался (нет овертайма/буллитов).
|
||
|
||
---
|
||
|
||
## 2. Установка и запуск
|
||
|
||
```bash
|
||
pip install pandas numpy matplotlib
|
||
|
||
# Полная турнирная таблица + таблицы по конференциям
|
||
python3 main.py khl_3/khl_2018_19.csv
|
||
|
||
# Гистограмма очков (по желанию — сохранить в файл)
|
||
python3 individual_1.py khl_3/khl_2018_19.csv [output.png]
|
||
|
||
# Гистограмма заброшенных шайб
|
||
python3 individual_4.py khl_3/khl_2018_19.csv
|
||
|
||
# Разница шайб команды в N-м периоде по датам
|
||
python3 individual_5.py khl_3/khl_2018_19.csv 2 "Ак Барс" [output.png]
|
||
```
|
||
|
||
> Имя файла важно: `main.py` достаёт код сезона (`2018_19`) из имени `khl_2018_19.csv`,
|
||
> чтобы понять, какие команды в какой конференции играли.
|
||
|
||
---
|
||
|
||
## 3. Как работает `main.py` (ядро проекта)
|
||
|
||
Логика построена на **векторных операциях pandas**: вычисления делаются сразу
|
||
над целым столбцом, без циклов по строкам.
|
||
|
||
**Шаг 1. `parse_score(df, col)`** — разбирает строку счёта `"3:1"` на два числа.
|
||
`str.split(':', expand=True)` раскладывает столбец в два, `to_numeric(..., errors='coerce')`
|
||
превращает текст в числа, а пустой период (`:`) через `fillna(0)` считается как `0:0`.
|
||
|
||
**Шаг 2. `build_standings(df, conf_map)`** — превращает список матчей в таблицу команд:
|
||
|
||
1. Считает голы в основное время (сумма трёх периодов).
|
||
2. Определяет **тип исхода** каждого матча сравнением столбцов:
|
||
победа в основное время / в овертайме / по буллитам — и аналогично поражения.
|
||
Победителю по буллитам добавляется ровно 1 решающая шайба.
|
||
3. **«Разворачивает» матч в две строки** — взгляд хозяев и взгляд гостей —
|
||
и склеивает их (`pd.concat`). Теперь у каждой команды по строке на матч.
|
||
4. `groupby('Команда').sum()` суммирует все показатели по командам.
|
||
5. Считает производные показатели:
|
||
* **И** — игры, **О** — очки (победа = 2, поражение в ОТ/буллитах = 1),
|
||
* **Р** — разница шайб, **%О** — процент набранных очков.
|
||
* `%О` считается с **отбрасыванием** знаков (`np.floor`), как на сайте КХЛ, а не округлением.
|
||
6. Сортирует по регламенту КХЛ: `%О → В → ВО → ВБ → Р → ГЗ`.
|
||
|
||
**Шаг 3. `show_table` и `main`** — печатают полную таблицу, затем отдельно
|
||
конференции Запад и Восток (фильтр по столбцу `Конф`).
|
||
|
||
### Обозначения столбцов
|
||
|
||
`И` — игры · `В` — победы в основное время · `ВО` — победы в овертайме ·
|
||
`ВБ` — победы по буллитам · `ПБ` — поражения по буллитам · `ПО` — поражения в овертайме ·
|
||
`П` — поражения в основное время · `ГЗ` — голы забитые · `ГП` — голы пропущенные ·
|
||
`Р` — разница · `О` — очки · `%О` — процент очков.
|
||
|
||
---
|
||
|
||
## 4. Индивидуальные задания
|
||
|
||
* **`individual_1.py`** — переиспользует `parse_score` из `main.py`, считает очки
|
||
каждой команды и строит **столбчатую диаграмму очков**. Поддерживает сохранение в PNG.
|
||
* **`individual_4.py`** — суммирует все заброшенные шайбы каждой команды за сезон
|
||
и строит гистограмму с подписями значений над столбцами.
|
||
* **`individual_5.py`** — фильтрует матчи одной команды, считает **разницу шайб
|
||
в выбранном периоде** по датам. Столбцы раскрашены: зелёный (плюс), красный (минус),
|
||
серый (ноль); добавлена линия нуля и сетка.
|
||
|
||
---
|
||
|
||
## 5. Материал к защите
|
||
|
||
**О чём проект.** По «сырым» результатам матчей КХЛ автоматически строится
|
||
официальная турнирная таблица и набор графиков. Цель — освоить обработку
|
||
табличных данных в pandas и визуализацию в matplotlib.
|
||
|
||
**Ключевые идеи, которые стоит назвать на защите:**
|
||
|
||
1. **Векторизация вместо циклов.** Все расчёты — операции над столбцами целиком
|
||
(сложение, сравнение, маски `True/False`). Это и быстрее, и короче, чем `for` по строкам.
|
||
2. **Приём «одна строка матча → две строки команд».** Чтобы посчитать статистику
|
||
команды, каждый матч дублируется: одна запись со стороны хозяев, другая — гостей.
|
||
После этого `groupby` сводит всё в таблицу команд.
|
||
3. **Булевы маски.** Тип исхода (победа/поражение и как именно) — это столбцы `True/False`,
|
||
которые переводятся в `1/0` через `.astype(int)` и суммируются.
|
||
4. **Точное соответствие регламенту КХЛ.** Система очков (2/1/0), добавление шайбы
|
||
за буллиты, отбрасывание (а не округление) процента очков, порядок критериев сортировки.
|
||
5. **Переиспользование кода.** `individual_1.py` импортирует функции из `main.py`,
|
||
чтобы не дублировать логику разбора счёта.
|
||
|
||
**Возможные вопросы и ответы:**
|
||
|
||
* *Почему пустой период = 0:0?* — Овертайм/буллиты есть не во всех матчах; `fillna(0)`
|
||
делает расчёт единообразным.
|
||
* *Почему `np.floor`, а не `round`?* — Сайт КХЛ отбрасывает знаки после второго
|
||
(72.448 → 72.44), а не округляет.
|
||
* *Зачем папка `khl_3_win`?* — то же содержимое, но с BOM, чтобы Excel правильно
|
||
показывал кириллицу.
|
||
* *Как добавить новый сезон?* — добавить CSV в `khl_3/` и описать конференции
|
||
в словаре `CONFERENCES` внутри `main.py`.
|