Daten in SPADL-Format umwandeln und speichern
Was ist das SPADL-Format?
SPADL (Soccer Player Action Description Language) ist ein Standard zur Beschreibung von Fußballaktionen. Dieser Standard wurde entwickelt, um eine einheitliche und detaillierte Darstellung von Aktionen auf dem Spielfeld zu ermöglichen, was die Analyse und Vergleichbarkeit von Daten erheblich verbessert.
Grundprinzipien von SPADL
Einheitliche Darstellung: SPADL bietet ein konsistentes Format zur Beschreibung von Fußballaktionen, das unabhängig von der Quelle der Daten ist. Dies erleichtert die Integration und Analyse von Daten aus verschiedenen Quellen.
Detaillierte Beschreibung: Jede Aktion wird mit einer Vielzahl von Merkmalen beschrieben, darunter:
Art der Aktion (z.B. Pass, Schuss, Dribbling)
Ausgangs- und Endposition (x- und y-Koordinaten)
Zeitpunkt der Aktion im Spiel (Spielminute)
Zusätzliche Attribute wie das verwendete Körperteil (Fuß, Kopf) und der Ausgang (erfolgreich, nicht erfolgreich)
Struktur von SPADL-Daten
SPADL-Daten sind in Form von Tabellen organisiert, wobei jede Zeile eine einzelne Aktion darstellt und die Spalten die verschiedenen Merkmale der Aktion enthalten. Wichtige Spalten sind unter anderem:
Game ID: Identifikation des Spiels
Action ID: Identifikation der Aktion
Type: Typ der Aktion (z.B. Pass, Shot)
Result: Ergebnis der Aktion (Success, Fail)
Start/End Coordinates: Start- und Endkoordinaten der Aktion
Body Part: Körperteil, mit dem die Aktion ausgeführt wurde
Time: Zeitpunkt der Aktion im Spiel
Vorteile von SPADL
Interoperabilität: Durch die standardisierte Darstellung können Daten aus verschiedenen Quellen leicht kombiniert und verglichen werden.
Detailtiefe: Die detaillierte Beschreibung ermöglicht tiefgehende Analysen und Einblicke in das Spielgeschehen.
Flexibilität: SPADL ist flexibel genug, um eine Vielzahl von Aktionen und Szenarien abzudecken, von einfachen Pässen bis hin zu komplexen Dribblings und Schüssen.
Laden, umwandeln und speichern der Daten in einer HDF5-Datei
Aktuell befinden sich all unsere Spiele in json-Files in einem Ordner. Diese Daten müssen wir nun laden und ins SPADL Format umwandeln, um sie später für die Modellierung verwenden zu können.
Ich bediene mich einerseits der OptaLoader Klasse, um die Spiele umzuwandeln. Andererseits brauche ich meinen eigenen Code, der prüft, ob bereits Spiele umgewandelt wurden.
Falls ja, dann müssen wir diese Spiele nicht noch einmal umwandeln, sondern können sie direkt aus der HDF5-Datei laden. Dies spart Zeit und Rechenleistung, wenn wir davon ausgehen, dass wir unsere Daten zum Beispiel wöchentlich aktualisieren wollen.
Am Ende speichern wir alle Spiele in einer HDF5-Datei ab, um sie später für die Modellierung zu verwenden.
HDF5
HDF5 ist ein Dateiformat, das speziell für große Datensätze entwickelt wurde. Es ermöglicht den schnellen Zugriff auf große Datenmengen und ist daher ideal für die Speicherung von SPADL-Daten geeignet.
Codebeispiel
Konkret sieht das nun so aus:
def load_convert_to_spadl_and_safe_all_matches_to_h5(datafolder: str, spadl_datafolder: str, competitions: pd.DataFrame) -> None:
"""
Load match data, convert it to SPADL format, and save it to an HDF5 file.
Args:
datafolder (str): Path to the data folder containing the event data.
spadl_datafolder (str): Path to the folder where the SPADL data will be saved.
competitions (pd.DataFrame): DataFrame containing competition and season information.
Returns:
None
"""
api = OptaLoader(root=datafolder, parser="whoscored")
# Get games from all selected competitions
games = pd.concat([
api.games(row.competition_id, row.season_id)
for row in competitions.itertuples()
])
print(f"Games loaded: {len(games)}")
games_verbose = tqdm.tqdm(list(games.itertuples()), desc="Loading game data")
teams, players = [], []
actions = {}
for game in games_verbose:
# Load data
teams.append(api.teams(game.game_id))
players.append(api.players(game.game_id))
events = api.events(game.game_id)
# Convert data
actions[game.game_id] = spadl.opta.convert_to_actions(events, game.home_team_id)
print(f"Games processed: {len(games)}")
teams = pd.concat(teams).drop_duplicates(subset="team_id")
players = pd.concat(players)
# Create data folder if it doesn't exist
if not os.path.exists(spadl_datafolder):
os.mkdir(spadl_datafolder)
print(f"Directory {spadl_datafolder} created.")
spadl_h5 = os.path.join(spadl_datafolder, "spadl-opta.h5")
# Store all SPADL data in h5-file
with pd.HDFStore(spadl_h5) as spadlstore:
spadlstore["competitions"] = competitions
spadlstore["games"] = games
spadlstore["teams"] = teams
spadlstore["players"] = players[['player_id', 'player_name']].drop_duplicates(subset='player_id')
spadlstore["player_games"] = players[['player_id', 'game_id', 'team_id', 'is_starter', 'minutes_played', 'starting_position']]
for game_id in actions.keys():
spadlstore[f"actions/game_{game_id}"] = actions[game_id]