Parsing custom events¶
In [1]:
Copied!
from kloppy import statsbomb
from kloppy.domain import ShotEvent, EventFactory, create_event, ShotEvent
from dataclasses import dataclass
from typing import Optional
import polars as pl
from kloppy import statsbomb
from kloppy.domain import ShotEvent, EventFactory, create_event, ShotEvent
from dataclasses import dataclass
from typing import Optional
import polars as pl
Define a custom shot event class¶
- Extends
ShotEventto includexg(expected goals). - Adds
inverted_xgproperty to compute1 - xG. - Overrides
__str__to provide a readable string representation.
In [2]:
Copied!
@dataclass(repr=False)
class StatsbombShotEvent(ShotEvent):
xg: Optional[float] = None
@property
def inverted_xg(self) -> Optional[float]:
if self.xg is not None:
return 1 - self.xg
else:
return None
def __str__(self):
return f"<Shot event_id='{self.event_id}' time='{self.time}' player='{self.player}' xg={self.xg} result='{self.result}'>"
@dataclass(repr=False)
class StatsbombShotEvent(ShotEvent):
xg: Optional[float] = None
@property
def inverted_xg(self) -> Optional[float]:
if self.xg is not None:
return 1 - self.xg
else:
return None
def __str__(self):
return f""
Implement a custom event factory¶
- Extracts xg from raw_event if available.
- Converts xG value to float.
- Uses create_event to construct a StatsbombShotEvent instance
In [3]:
Copied!
class StatsbombEventFactory(EventFactory):
def build_shot(self, raw_event, **kwargs) -> ShotEvent:
xg = (
raw_event["shot"]["statsbomb_xg"]
if "shot" in raw_event and raw_event["shot"]
else None
)
if xg is not None:
xg = float(xg)
return create_event(
StatsbombShotEvent,
xg=xg,
raw_event=raw_event,
**kwargs,
)
class StatsbombEventFactory(EventFactory):
def build_shot(self, raw_event, **kwargs) -> ShotEvent:
xg = (
raw_event["shot"]["statsbomb_xg"]
if "shot" in raw_event and raw_event["shot"]
else None
)
if xg is not None:
xg = float(xg)
return create_event(
StatsbombShotEvent,
xg=xg,
raw_event=raw_event,
**kwargs,
)
For the sake of this demonstration, we will use Statsbomb Open Event Data and apply our custom EventFactory
In [4]:
Copied!
dataset = statsbomb.load_open_data(
match_id=15946,
# Optional arguments
coordinates="statsbomb",
event_factory=StatsbombEventFactory(), # Use our custom EventFactory
)
dataset = statsbomb.load_open_data(
match_id=15946,
# Optional arguments
coordinates="statsbomb",
event_factory=StatsbombEventFactory(), # Use our custom EventFactory
)
/cw/dtaijupiter/NoCsBack/dtai/pieterr/Projects/kloppy/kloppy/_providers/statsbomb.py:83: UserWarning: You are about to use StatsBomb public data. By using this data, you are agreeing to the user agreement. The user agreement can be found here: https://github.com/statsbomb/open-data/blob/master/LICENSE.pdf warnings.warn(
Filter and print shots¶
In [5]:
Copied!
shots = dataset.filter("shot")
for shot in shots[:5]:
print(shot)
shots = dataset.filter("shot")
for shot in shots[:5]:
print(shot)
<Shot event_id='becd7956-ce44-479e-8fc9-16a2d1f1f349' time='P1T02:29' player='Lionel Andrés Messi Cuccittini' xg=0.07699243 result='OFF_TARGET'> <Shot event_id='9107d374-2942-4876-a14f-1b9f86901c15' time='P1T05:40' player='Jordi Alba Ramos' xg=0.05166811 result='OFF_TARGET'> <Shot event_id='ddd194ca-08fb-43d0-87c2-33647f975f9f' time='P1T15:29' player='Lionel Andrés Messi Cuccittini' xg=0.016932096 result='SAVED'> <Shot event_id='86596ddb-d824-4e5e-b18c-b4442e9ce7cf' time='P1T16:20' player='Rubén Sobrino Pozuelo' xg=0.1226044 result='OFF_TARGET'> <Shot event_id='3ed2b107-be17-42d5-9d1b-25006a0e55cb' time='P1T18:16' player='Luis Alberto Suárez Díaz' xg=0.041750744 result='OFF_TARGET'>
Use the inverted_xg property¶
In [6]:
Copied!
for shot in shots[:5]:
print(shot.inverted_xg)
for shot in shots[:5]:
print(shot.inverted_xg)
0.92300757 0.94833189 0.983067904 0.8773956 0.958249256
Convert shots to a Polars DataFrame¶
In [7]:
Copied!
shots.to_df("player_id", "xg", engine="polars")
shots.to_df("player_id", "xg", engine="polars")
Out[7]:
shape: (28, 2)
| player_id | xg |
|---|---|
| str | f64 |
| "5503" | 0.076992 |
| "5211" | 0.051668 |
| "5503" | 0.016932 |
| "6613" | 0.1226044 |
| "5246" | 0.041751 |
| … | … |
| "6935" | 0.140808 |
| "3501" | 0.334535 |
| "3501" | 0.105343 |
| "5503" | 0.09483 |
| "5503" | 0.420624 |
In [ ]:
Copied!