Metadata-Version: 2.5
Name: duckstatsbomb
Version: 0.4.0
Summary: A data parser for Hudl StatsBomb soccer data using duckdb
Project-URL: Documentation, https://duckstatsbomb.readthedocs.io
Project-URL: Issues, https://github.com/andrewRowlinson/duckstatsbomb/issues
Project-URL: Source, https://github.com/andrewRowlinson/duckstatsbomb
Author-email: Andrew Rowlinson <rowlinsonandy@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: football,soccer,statsbomb
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.11
Requires-Dist: duckdb>=1.4.1
Provides-Extra: all
Requires-Dist: pandas; extra == 'all'
Requires-Dist: polars; extra == 'all'
Requires-Dist: pyarrow; extra == 'all'
Provides-Extra: arrow
Requires-Dist: pyarrow; extra == 'arrow'
Provides-Extra: pandas
Requires-Dist: pandas; extra == 'pandas'
Provides-Extra: polars
Requires-Dist: polars; extra == 'polars'
Requires-Dist: pyarrow; extra == 'polars'
Description-Content-Type: text/markdown

# duckstatsbomb
Get flat tables from Hudl StatsBomb data, in multiple formats, in seconds once cached.

DuckDB does the parsing in parallel. You can parse a whole Premier League season of
1.3 million events from JSON into pandas, Polars or Arrow tables in a few seconds.
Or use the default output, a DuckDB relation, and filter to the shots and sum the xG
before building a DataFrame, so you can query the whole open-data set on your laptop.

Docs available at: https://duckstatsbomb.readthedocs.io

# Installation
The duckstatsbomb default has one dependency, DuckDB.
You can install optional dependencies to export to pandas, Polars, or Arrow:

```bash
pip install duckstatsbomb
pip install "duckstatsbomb[pandas]"  # pandas
pip install "duckstatsbomb[polars]"  # Polars & PyArrow
pip install "duckstatsbomb[arrow]"  # PyArrow
pip install "duckstatsbomb[all]"  # pandas, Polars & PyArrow
```

# Output formats

By default the library outputs a DuckDBPyRelation,
which you can filter, aggregate, or query.

```python
from duckstatsbomb import Sbopen
parser = Sbopen()
events = parser.competition_data(competition_id=43, season_id=106, kind='events')
shots = events.filter("type_name = 'Shot'")
# top 4 goal scorers at the 2022 World Cup
top = (
    shots.aggregate(
        'player_name, team_name, count(*) as shots, '
        'round(sum(shot_statsbomb_xg), 2) as xg, '
        "count(*) filter (outcome_name = 'Goal') as goals",
        'player_name, team_name',
    )
    .order('goals desc, xg desc')
    .limit(4)
)
top.show()
```

You can also export to different formats:
```python
df_pandas = shots.df()  # pip install "duckstatsbomb[pandas]"
df_polars = shots.pl()  # pip install "duckstatsbomb[polars]"
arrow_table = shots.to_arrow_table()  # pip install "duckstatsbomb[arrow]"
shots.to_csv('world_cup_2022_shots.csv')
shots.to_parquet('world_cup_2022_shots.parquet')
```

Or set the output format when creating the parser:
```python
parser = Sbopen(output_format='pandas')  # 'relation', 'pandas', 'polars' or 'arrow'
```

# Three parsers

There are three parsers: Sbopen, Sbapi, and Sbfiles.

All three have common methods: `competitions` (competition info),
`matches` (match info), and `match_data` (event, lineup, and three-sixty info).
Sbopen and Sbapi also include `competition_data` for getting whole season
data (event, lineups, and three-sixty).

## Competitions data
```python
from duckstatsbomb import Sbopen  # or Sbapi/Sbfiles
parser = Sbopen()  # or Sbapi() / Sbfiles()
competitions = parser.competitions()  # filenames for Sbfiles
```

## Matches data
```python
from duckstatsbomb import Sbopen  # or Sbapi/Sbfiles
parser = Sbopen()  # or Sbapi() / Sbfiles()
matches = parser.matches(2, 44)  # filenames for Sbfiles
```

## Event data
```python
from duckstatsbomb import Sbopen  # or Sbapi/Sbfiles
parser = Sbopen()  # or Sbapi() / Sbfiles()
# see parser.kinds for valid kind
events = parser.match_data(3857254, kind='events')  # filenames for Sbfiles
```

## Competition/season data
```python
from duckstatsbomb import Sbopen  # or Sbapi
parser = Sbopen()  # or Sbapi()
# see parser.kinds for valid kind
# no method for Sbfiles
lineup_players = parser.competition_data(competition_id=43, season_id=106,
                                         kind='lineup_players')
```

Sbapi needs a Hudl StatsBomb API subscription.
Pass the username and password as class arguments,
or set the SB_USERNAME and SB_PASSWORD environment variables.

# Cache

Sbopen and Sbapi cache the downloaded match files as raw JSON in the
`cache_path` directory. You can list the cache, delete the files for
particular matches, or delete the whole directory.

```python
from duckstatsbomb import Sbopen
parser = Sbopen()
parser.cached_files()  # path, size and UTC download time of each file
parser.sources  # the match files: ['events', 'lineups', 'threesixty']
parser.stale_matches(43, 106, source='events')  # identify stale match IDs
parser.clear_match_data([3857254, 3857255], source='events')
parser.clear_cache()
```

The competitions and matches files are never cached, as they may change
often when Hudl StatsBomb release or reprocess data.

You can turn off the cache with the class argument `cache_enabled`,
change the `cache_path` or design your own cache backend and pass it to `cache`.
