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]