# chickenstats

<div style="text-align: center;">

[![Hero image - scatter plot with drumsticks and tooltips](https://raw.githubusercontent.com/chickenandstats/chickenstats/main/assets/hero_transparent.png)](https://chickenstats.com)

[![PyPI - Version](https://img.shields.io/pypi/v/chickenstats?color=BrightGreen)](https://pypi.org/project/chickenstats)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/chickenstats?color=BrightGreen)](https://pypi.org/project/chickenstats)
[![tests](https://github.com/chickenandstats/chickenstats/actions/workflows/tests.yml/badge.svg)](https://github.com/chickenandstats/chickenstats/actions/workflows/tests.yml)
[![codecov](https://codecov.io/gh/chickenandstats/chickenstats/graph/badge.svg?token=Z1ETX5L8FL)](https://codecov.io/gh/chickenandstats/chickenstats)
![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/chickenandstats/chickenstats?color=BrightGreen)
![GitHub License](https://img.shields.io/github/license/chickenandstats/chickenstats?color=BrightGreen)

</div>

---

## About

* **Scrape & manipulate** data from various NHL endpoints, leveraging
[:material-hockey-sticks: chicken_nhl](reference/chicken_nhl/scrape.md), which includes
an **open-source xG model** for shot quality metrics
* **Augment play-by-play data** & **generate custom aggregations** from raw csv files downloaded from
[Evolving-Hockey](https://evolving-hockey.com) *(subscription required)* with
[:material-hockey-puck: evolving_hockey](reference/evolving_hockey/stats.md)

For more in-depth explanations, tutorials, & detailed reference materials, consult the
[**Documentation**](https://chickenstats.com). 

---

## Compatibility

`chickenstats` requires Python 3.10 or greater & runs on the latest stable versions of Linux, Mac, & Windows
operating systems.

---

## Installation

Very simple - install using PyPi. Best practice is to develop in an isolated virtual environment (conda or otherwise),
but who's a chicken to judge?

```sh
pip install chickenstats
```

To confirm installation & the latest version (1.8.0):

```sh
pip show chickenstats
```

---

## Usage

`chickenstats` is structured as two underlying modules, each used with different data sources:
* `chickenstats.chicken_nhl`
* `chickenstats.evolving_hockey`

The packages and resulting outputs are largely interchangeable, with similar fields across `chicken_nhl` 
and `evolving_hockey` packages, including high-danger scoring chances, score- and venue-adjusted fenwick, 
corsi, and xG.

Feel free to use whichever package and data source that you prefer. If you have questions about differences between
packages, you can find me on :simple-bluesky: Bluesky at **[@chickenandstats.com](https://bsky.app/profile/chickenandstats.com)**
or :material-email: email me at **[chicken@chickenandstats.com](mailto:chicken@chickenandstats.com)**.

Please note that `chickenstats` is under active development - features will continue to be added or modified over time. 

### chicken_nhl

`chickenstats.chicken_nhl` allows you to scrape play-by-play data and aggregate individual, line, and team statistics.
After importing the module, scrape the schedule for game IDs, then play-by-play data for your team of choice:

```python
from chickenstats.chicken_nhl import Season, Scraper

season = Season(2024)

schedule = season.schedule("NSH")
game_ids = schedule.loc[schedule.game_state == "OFF"].game_id.tolist()

scraper = Scraper(game_ids)

play_by_play = scraper.play_by_play
```

You can then aggregate the play-by-play data for individual and on-ice statistics with one line of code:

```python
stats = scraper.stats
```

It's very easy to introduce additional detail to, as well as change the level of, aggregations, 
including for season-level statistics accounting for teammates on-ice:

```python
scraper.prep_stats(level="season", teammates=True)
stats = scraper.stats
```

> [!TIP]
> The Scraper object saves the prior aggregation to the `scraper.stats` attribute, so it needs to be reset.
> Then the attribute can be re-called, with a different level of aggregation

There is similar functionality for forward line / defensive pairing stats:

```python
scraper.prep_lines(position="f") # (1)!
forward_lines = scraper.lines

scraper.prep_lines(position="d", level="season")
defense_lines = scraper.lines # (2)!
```

> [!TIP]
> This step isn't strictly necessary for the forwards - they're the default line aggregation. Provide "d" instead of "f"
> for defensive line stats

As well as for team stats:

```python
team_stats = scraper.team_stats # (1)!
```

For additional information on usage and functionality, consult the relevant
[user guide](https://chickenstats.com/latest/guide/chicken_nhl/chicken_nhl/)

### evolving_hockey
 
The `chickenstats.evolving_hockey` module manipulates raw csv files downloaded from
[Evolving-Hockey](https://evolving-hockey.com). Using their original shifts & play-by-play data, users can add additional
information & aggregate for individual & on-ice statistics,
including high-danger shooting events, xG & adjusted xG, faceoffs, & changes.

First, prep a play-by-play dataframe using raw play-by-play and shifts CSV files from the
[Evolving-Hockey website](https://evolving-hockey.com):

```python
import pandas as pd
from chickenstats.evolving_hockey import prep_pbp, prep_stats, prep_lines

raw_shifts = pd.read_csv('./raw_shifts.csv')
raw_pbp = pd.read_csv('./raw_pbp.csv')

play_by_play = prep_pbp(raw_pbp, raw_shifts)
```

You can use the play_by_play dataframe in various aggregations. This will return individual game statistics,
including on-ice (e.g., GF, xGF) & usage (i.e., zone starts), accounting for teammates & opposition on-ice:

```python
individual_game = prep_stats(play_by_play, level='game', teammates=True, opposition=True)
```

This will return game statistics for forward-line combinations, accounting for opponents on-ice:

```python
forward_lines = prep_lines(play_by_play, level='game', position='f', opposition=True)
```

For additional information on usage and functionality, consult the relevant
[user guide](https://chickenstats.com/latest/guide/evolving_hockey/evolving_hockey/)

---

## **Help**

If you need help with any aspect of `chickenstats`, from installation to usage, please don't hesitate to reach out!
You can find me on :material-bluesky: Bluesky at **[@chickenandstats.com](https://bsky.app/profile/chickenandstats.com)** or :material-email: 
email me at **[chicken@chickenandstats.com](mailto:chicken@chickenandstats.com)**.

Please report any bugs or issues via the `chickenstats` **[issues](https://github.com/chickenandstats/chickenstats/issues)** page, where you can also post feature requests.
Before doing so, please check the [roadmap](https://chickenstats.com/latest/contribute/roadmap/), there might already be plans to include your request.

---

## Acknowledgements

`chickenstats` wouldn't be possible without the support & efforts of countless others. I am obviously
extremely grateful, even if there are too many of you to thank individually. However, this chicken will do his best.

First & foremost is my wife - the lovely Mrs. Chicken has been patient, understanding, & supportive throughout the countless
hours of development, sometimes to her detriment.

Sincere apologies to the friends & family that have put up with me since my entry into Python, programming, & data
analysis in January 2021. Thank you for being excited for me & with me throughout all of this, especially when you've
had to fake it...

Thank you to the hockey analytics community on (the artist formerly known as) Twitter. You're producing
& reacting to cutting-edge statistical analyses, while providing a supportive, welcoming environment for newcomers.
Thank y'all for everything that you do. This is by no means exhaustive, but there are a few people worth
calling out specifically:
* Josh & Luke Younggren ([@EvolvingWild](https://twitter.com/EvolvingWild))
* Bryan Bastin ([@BryanBastin](https://twitter.com/BryanBastin))
* Max Tixador ([@woumaxx](https://twitter.com/woumaxx))
* Micah Blake McCurdy ([@IneffectiveMath](https://twitter.com/IneffectiveMath))
* Prashanth Iyer ([@iyer_prashanth](https://twitter.com/iyer_prashanth))
* The Bucketless ([@the_bucketless](https://twitter.com/the_bucketless))
* Shayna Goldman ([@hayyyshayyy](https://twitter.com/hayyyshayyy))
* Dom Luszczyszyn ([@domluszczyszyn](https://twitter.com/domluszczyszyn))
* Carlie Markey ([@quarkyhockey](https://twitter.com/quarkyhockey))
* An Nguyen ([@nguyenank.bsky.social](https://bsky.app/profile/nguyenank.bsky.social))

I'm also grateful to the thriving community of Python educators & open-source contributors on Twitter. Thank y'all
for your knowledge & practical advice. Matt Harrison ([@__mharrison__](https://twitter.com/__mharrison__))
deserves a special mention for his books on Pandas and XGBoost, both of which are available at his online
[store](https://store.metasnake.com). Again, not exhaustive, but others worth thanking individually:
* Will McGugan ([@willmcgugan](https://twitter.com/willmcgugan))
* Rodrigo Girão Serrão ([@mathsppblog](https://twitter.com/mathsppblog))
* Mike Driscoll ([@driscollis](https://twitter.com/driscollis))
* Trey Hunner ([@treyhunner](https://twitter.com/treyhunner))
* Pawel Jastrzebski ([@pawjast](https://twitter.com/pawjast))

Finally, this library depends on a host of other open-source packages. `chickenstats` is possible because of the efforts
of thousands of individuals, represented below:
* [Pandas](https://pandas.pydata.org)
* [scikit-Learn](https://scikit-learn.org/stable/)
* [matplotlib](https://matplotlib.org)
* [Rich](https://github.com/Textualize/rich)
* [Pydantic](https://github.com/pydantic/pydantic)
* [Pandera](https://pandera.readthedocs.io/en/stable/)
* [XGBoost](https://xgboost.readthedocs.io/en/stable/)
* [Mkdocs](https://www.mkdocs.org)
* [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
* [MlFlow](https://mlflow.org/docs/latest/index.html)
* [Optuna](https://optuna.readthedocs.io/en/stable/)
* [Black](https://github.com/psf/black)
* [Ruff](https://github.com/astral-sh/ruff)
* [uv](https://github.com/astral-sh/uv)
* [Jupyter](https://jupyter.org)
* [Pytest](https://docs.pytest.org/en/8.2.x/)
* [Tox](https://tox.wiki/en/4.15.0/)
* [Caddy](https://caddyserver.com)
* [Yellowbrick](https://www.scikit-yb.org/en/latest/)
* [Shap](https://shap.readthedocs.io/en/latest/)
* [Seaborn](https://seaborn.pydata.org)
* [hockey-rink](https://github.com/the-bucketless/hockey_rink)
