lastScore Results Data

lastScore Results Data#

Accessing stage and overal results and timing data.

This is probably the data you’re most interested in, so let’s get stuck into it.

The data is defined at the category and stage level and includes stages results and timing data at each lastscore, as well as at stage end, as well as overall timing and results classification data.

# Load in the required packages
import pandas as pd
from jupyterlite_simple_cors_proxy import furl, xurl

# Generate the API URL pattern
dakar_api_template = "https://www.dakar.live.worldrallyraidchampionship.com/api/{path}"

# Define the year
YEAR = 2025
# Define the category
CATEGORY = "A"
# Define the stage
STAGE = 1

# Define the API path to the stage resource
# Use a Python f-string to instantiate variable values directly
lastscore_path = f"lastScore-{YEAR}-{CATEGORY}-{STAGE}"

# Define the URL
lastscore_url = dakar_api_template.format(path=lastscore_path)

# Preview the path and the URL
lastscore_path, lastscore_url
('lastScore-2025-A-1',
 'https://www.dakar.live.worldrallyraidchampionship.com/api/lastScore-2025-A-1')

The JSON object returned by the live data service for the lastScore results feeds is quite a deepy nested data structure that returns a complex dataframe is parsed directly using the read_json() function:

# Load in data
# Use furl() to handle CORS issues in Jupyterlite
_lastscore_df = pd.read_json(furl(lastscore_url))
_lastscore_df.head(2)
team dss bonif cg cs ce _bind _updatedAt _id fsh wd
0 {'bib': 427, 'clazz': '9a68ed3c41c5c7a1642df5d... {'position': 130, 'absolute': 40650000, 'inter... {'total': 0, 'wp': []} {'01216': {'position': [128, 128], 'absolute':... {'01207': {'position': [129, 129], 'absolute':... {'position': [125, 125], 'absolute': [23353000... lastScore-2025-A-1 1737386238243 lastScore-2025-A-1-427 NaN NaN
1 {'bib': 634, 'clazz': 'ec2f26ebeb14824160c7204... {'position': 171, 'absolute': 41910000, 'inter... {'total': 0, 'wp': []} {'01216': {'position': [194, 194], 'absolute':... {'01207': {'position': [179, 179], 'absolute':... {'position': [196, 197], 'absolute': [11880000... lastScore-2025-A-1 1737386237448 lastScore-2025-A-1-634 NaN NaN

We can get a much better behaved data structure if we parse the JSON directly using the pd.json_normalize() function:

import requests
pd.json_normalize(requests.get(lastscore_url).json()).head()
_bind _updatedAt _id team.bib team.clazz team.brand team.model team.competitors team.vehicle team.vehicleImg ... ce.relative ce.bonus cg.01ASS.penality cs.01ASS.penality ce.penality cg.01227.position cg.01227.absolute cg.01227.relative fsh wd
0 lastScore-2025-A-1 1737386238243 lastScore-2025-A-1-427 427 9a68ed3c41c5c7a1642df5d93458baa6 BRP CAN-AM MAVERICK R [{'name': 'B. LEPIETRE', 'firstName': 'BENOIT'... BTR https://img.aso.fr/core_app/img-motorSports-da... ... [6845000, 6845000] 0 NaN NaN NaN NaN NaN NaN NaN NaN
1 lastScore-2025-A-1 1737386237448 lastScore-2025-A-1-634 634 ec2f26ebeb14824160c7204618a5780d DAF FAV 85 MX [{'name': 'J. ESTEVE ORO', 'firstName': 'JORDI... TIBAU TEAM https://img.aso.fr/core_app/img-motorSports-da... ... [102292000, 102292000] 0 79200000.0 79200000.0 79200000.0 NaN NaN NaN NaN NaN
2 lastScore-2025-A-1 1737386237841 lastScore-2025-A-1-330 330 a0a6386a4b9a61b73b036a50966345c0 TAURUS T3 MAX [{'name': 'A. ALKUWARI', 'firstName': 'AHMED F... NASSER RACING https://img.aso.fr/core_app/img-motorSports-da... ... [1672000, 1672000] 0 NaN NaN NaN NaN NaN NaN NaN NaN
3 lastScore-2025-A-1 1737386238131 lastScore-2025-A-1-243 243 f00d7ec8d2d96e9cf11aa515109376cf MD OPTIMUS [{'name': 'P. THOMASSE', 'firstName': 'PASCAL'... MD RALLYE SPORT https://img.aso.fr/core_app/img-motorSports-da... ... [2160000, 2160000] 0 NaN NaN NaN NaN NaN NaN NaN NaN
4 lastScore-2025-A-1 1737386238128 lastScore-2025-A-1-404 404 9a68ed3c41c5c7a1642df5d93458baa6 BRP CAN-AM MAVERICK R [{'name': 'F. LOPEZ CONTARDO', 'firstName': 'F... CAN-AM FACTORY TEAM https://img.aso.fr/core_app/img-motorSports-da... ... [1510000, 1510000] 0 NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 88 columns

# Rather than re-download the JSON data using requests,
# (remembering to use xurl() for JupyterLite CORS handling)
# we can convert the dataframe back to JSON
_lastscore_json = _lastscore_df.to_dict('records')

# Now we can use the more powerful json_normalize() function
# to generate a dataframe from the data
_results_df = pd.json_normalize(_lastscore_json)

_results_df.head()
_bind _updatedAt _id fsh wd team.bib team.clazz team.brand team.model team.competitors ... ce.position ce.absolute ce.relative ce.bonus cg.01ASS.penality cs.01ASS.penality ce.penality cg.01227.position cg.01227.absolute cg.01227.relative
0 lastScore-2025-A-1 1737386238243 lastScore-2025-A-1-427 NaN NaN 427 9a68ed3c41c5c7a1642df5d93458baa6 BRP CAN-AM MAVERICK R [{'name': 'B. LEPIETRE', 'firstName': 'BENOIT'... ... [125, 125] [23353000, 23353000] [6845000, 6845000] 0 NaN NaN NaN NaN NaN NaN
1 lastScore-2025-A-1 1737386237448 lastScore-2025-A-1-634 NaN NaN 634 ec2f26ebeb14824160c7204618a5780d DAF FAV 85 MX [{'name': 'J. ESTEVE ORO', 'firstName': 'JORDI... ... [196, 197] [118800000, 118800000] [102292000, 102292000] 0 79200000.0 79200000.0 79200000.0 NaN NaN NaN
2 lastScore-2025-A-1 1737386237841 lastScore-2025-A-1-330 NaN NaN 330 a0a6386a4b9a61b73b036a50966345c0 TAURUS T3 MAX [{'name': 'A. ALKUWARI', 'firstName': 'AHMED F... ... [43, 43] [18180000, 18180000] [1672000, 1672000] 0 NaN NaN NaN NaN NaN NaN
3 lastScore-2025-A-1 1737386238131 lastScore-2025-A-1-243 NaN NaN 243 f00d7ec8d2d96e9cf11aa515109376cf MD OPTIMUS [{'name': 'P. THOMASSE', 'firstName': 'PASCAL'... ... [50, 50] [18668000, 18668000] [2160000, 2160000] 0 NaN NaN NaN NaN NaN NaN
4 lastScore-2025-A-1 1737386238128 lastScore-2025-A-1-404 NaN NaN 404 9a68ed3c41c5c7a1642df5d93458baa6 BRP CAN-AM MAVERICK R [{'name': 'F. LOPEZ CONTARDO', 'firstName': 'F... ... [34, 34] [18018000, 18018000] [1510000, 1510000] 0 NaN NaN NaN NaN NaN NaN

5 rows × 88 columns

Inspection of the dataframe column names shows how the .json_normalize() function flattened nested objects into and created flattened, dotted column names that reveal the original nested object data paths.

_results_df.columns
Index(['_bind', '_updatedAt', '_id', 'fsh', 'wd', 'team.bib', 'team.clazz',
       'team.brand', 'team.model', 'team.competitors', 'team.vehicle',
       'team.vehicleImg', 'team.w2rc', 'dss.position', 'dss.absolute',
       'dss.real', 'bonif.total', 'bonif.wp', 'cg.01216.position',
       'cg.01216.absolute', 'cg.01216.relative', 'cg.01218.position',
       'cg.01218.absolute', 'cg.01218.relative', 'cg.01224.position',
       'cg.01224.absolute', 'cg.01224.relative', 'cg.01207.position',
       'cg.01207.absolute', 'cg.01207.relative', 'cg.01233.position',
       'cg.01233.absolute', 'cg.01233.relative', 'cg.01230.position',
       'cg.01230.absolute', 'cg.01230.relative', 'cg.01222.position',
       'cg.01222.absolute', 'cg.01222.relative', 'cg.01220.position',
       'cg.01220.absolute', 'cg.01220.relative', 'cg.01ASS.position',
       'cg.01ASS.absolute', 'cg.01ASS.relative', 'cg.01ASS.bonus',
       'cg.01ASS.stagePenalty', 'cs.01207.position', 'cs.01207.absolute',
       'cs.01207.relative', 'cs.01218.position', 'cs.01218.absolute',
       'cs.01218.relative', 'cs.01220.position', 'cs.01220.absolute',
       'cs.01220.relative', 'cs.01216.position', 'cs.01216.absolute',
       'cs.01216.relative', 'cs.01227.position', 'cs.01227.absolute',
       'cs.01227.relative', 'cs.01230.position', 'cs.01230.absolute',
       'cs.01230.relative', 'cs.01222.position', 'cs.01222.absolute',
       'cs.01222.relative', 'cs.01233.position', 'cs.01233.absolute',
       'cs.01233.relative', 'cs.01224.position', 'cs.01224.absolute',
       'cs.01224.relative', 'cs.01ASS.position', 'cs.01ASS.absolute',
       'cs.01ASS.relative', 'cs.01ASS.bonus', 'ce.position', 'ce.absolute',
       'ce.relative', 'ce.bonus', 'cg.01ASS.penality', 'cs.01ASS.penality',
       'ce.penality', 'cg.01227.position', 'cg.01227.absolute',
       'cg.01227.relative'],
      dtype='object')

We might also notice that as well as the cg and cs results fields, which are annotated with what we might assume to be waypoint identifiers, the dataframe includes team and crew information which is not directly associated with a particular stage, but is rather more generic. There are also stage start (dss) and stage end (ce) indications.

It therefore makes sense to extract this data from the data frame, so that we might store it separately (we might also assume that the crew and team information will be fixed throughout the rally? Or are crew changes allowed during the rally?)

The following function

import pandas as pd
from typing import Tuple


def normalize_team_competitors(df: pd.DataFrame, year: int = 2025) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
    """
    Transform a DataFrame containing nested competitor lists into three slighly more normalized DataFrames.
    
    Args:
        df (pd.DataFrame): Input DataFrame with columns including 'team.bib', 'team.model', and 'team.competitors' (list of dicts)
    
    Returns:
        Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: (teams_df, competitors_df, results_df)
            - teams_df: DataFrame with team information
            - competitors_df: DataFrame with competitor information
            - results_df: DataFrame of results;
    """

    # Create competitors DataFrame using explode and json_normalize
    competitors_df = (
        df[['team.bib', 'team.competitors']]
        .explode('team.competitors')
        .reset_index(drop=True)
    )

    # Normalize the dictionary contents and combine with team.bib
    competitors_df = pd.concat([
        competitors_df['team.bib'],
        pd.json_normalize(competitors_df['team.competitors'])
    ], axis=1)

    competitors_df["year"] = year

    # Create teams DataFrame by dropping the competitors column
    teams_df = df.drop('team.competitors', axis=1)
    team_cols = [c for c in teams_df.columns if c.startswith(
        "team")]
    teams_df = teams_df[team_cols]

    team_cols.remove("team.bib")
    team_cols.append("team.competitors")
    return teams_df, competitors_df, df.drop(team_cols, axis=1)

Applying this function splits out the team, competitor, and results data.

teams_df, competitors_df, _results = normalize_team_competitors(_results_df)
# Preview the team data
teams_df.head()
team.bib team.clazz team.brand team.model team.vehicle team.vehicleImg team.w2rc
0 427 9a68ed3c41c5c7a1642df5d93458baa6 BRP CAN-AM MAVERICK R BTR https://img.aso.fr/core_app/img-motorSports-da... False
1 634 ec2f26ebeb14824160c7204618a5780d DAF FAV 85 MX TIBAU TEAM https://img.aso.fr/core_app/img-motorSports-da... False
2 330 a0a6386a4b9a61b73b036a50966345c0 TAURUS T3 MAX NASSER RACING https://img.aso.fr/core_app/img-motorSports-da... False
3 243 f00d7ec8d2d96e9cf11aa515109376cf MD OPTIMUS MD RALLYE SPORT https://img.aso.fr/core_app/img-motorSports-da... False
4 404 9a68ed3c41c5c7a1642df5d93458baa6 BRP CAN-AM MAVERICK R CAN-AM FACTORY TEAM https://img.aso.fr/core_app/img-motorSports-da... False
# Preview the competitors data
competitors_df.head()
team.bib name firstName lastName role gender nationality profil profil_sm podium aid year
0 427 B. LEPIETRE BENOIT LEPIETRE P m fra https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... 110add16-df63-4b90-9494-bc3db7d02662 2025
1 427 R. RELMY-MADINSKA RODRIGUE RELMY-MADINSKA C m fra https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... 63cb271c-1c74-4f07-82b4-c3df3c425aa7 2025
2 634 J. ESTEVE ORO JORDI ESTEVE ORO P m esp https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... 36106f23-d545-47b9-8565-983cce7550d3 2025
3 634 F. PARDO FRANCESC PARDO C m esp https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... 43c1ce16-ccee-4ac2-ae16-b89e82a43183 2025
4 634 J. PUJOL FORNOS JORDI PUJOL FORNOS M m esp https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... https://img.aso.fr/core_app/img-motorSports-da... 7700b503-68b6-4aca-a63a-96047071c2e9 2025
# Preview the results data
_results.head()
_bind _updatedAt _id fsh wd team.bib dss.position dss.absolute dss.real bonif.total ... ce.position ce.absolute ce.relative ce.bonus cg.01ASS.penality cs.01ASS.penality ce.penality cg.01227.position cg.01227.absolute cg.01227.relative
0 lastScore-2025-A-1 1737386238243 lastScore-2025-A-1-427 NaN NaN 427 130 40650000 True 0 ... [125, 125] [23353000, 23353000] [6845000, 6845000] 0 NaN NaN NaN NaN NaN NaN
1 lastScore-2025-A-1 1737386237448 lastScore-2025-A-1-634 NaN NaN 634 171 41910000 True 0 ... [196, 197] [118800000, 118800000] [102292000, 102292000] 0 79200000.0 79200000.0 79200000.0 NaN NaN NaN
2 lastScore-2025-A-1 1737386237841 lastScore-2025-A-1-330 NaN NaN 330 55 38370000 True 0 ... [43, 43] [18180000, 18180000] [1672000, 1672000] 0 NaN NaN NaN NaN NaN NaN
3 lastScore-2025-A-1 1737386238131 lastScore-2025-A-1-243 NaN NaN 243 67 38730000 True 0 ... [50, 50] [18668000, 18668000] [2160000, 2160000] 0 NaN NaN NaN NaN NaN NaN
4 lastScore-2025-A-1 1737386238128 lastScore-2025-A-1-404 NaN NaN 404 72 38880000 True 0 ... [34, 34] [18018000, 18018000] [1510000, 1510000] 0 NaN NaN NaN NaN NaN NaN

5 rows × 81 columns

The results dataframe still looks rather cluttered. Inspection of the data, and comparison back with the parent webiste, suggests the following interpretation for some of the results data columns:

  • ce: end of stage status

  • dss: stage start status

For waypoints:

  • cg: overall status at waypoint

  • cs: stage status at waypoint

Ideally, we would like to be able retrieve different collections of results data in a natural way.

For example, we might want to query:

  • the end of stage positions for each crew;

  • the positions of each crew at a particular waypoint;

  • time differences or gap to leader at stage end, or at a particular waypoint;

  • the position of a particular crew at each waypoint.

Having the data in a particular form can often make it easier — or harder — to make these sorts of query.

id_column = "_id"
point_cols = [col for col in _results.columns if col.startswith(('cg', 'cs'))]
# Melt only the point-specific columns
melted = _results[[id_column, "team.bib", *point_cols]
                  ].melt(id_vars=[id_column, "team.bib"]).dropna()
melted = melted[melted['variable'].str.contains('position|absolute|relative')]
melted["type"] = melted["variable"].str.split('.').str[0]
melted["waypoint"] = melted["variable"].str.extract(r'\.([^\.]+)\.')
melted["metric"] = melted["variable"].str.split('.').str[-1]


melted[['value_0', 'value_1']] = pd.DataFrame(
    melted['value'].tolist(),
    index=melted.index
)

melted.drop(columns=["variable", "value"], inplace=True)

melted
_id team.bib type waypoint metric value_0 value_1
0 lastScore-2025-A-1-427 427 cg 01216 position 128 128
1 lastScore-2025-A-1-634 634 cg 01216 position 194 194
2 lastScore-2025-A-1-330 330 cg 01216 position 53 53
3 lastScore-2025-A-1-243 243 cg 01216 position 60 60
4 lastScore-2025-A-1-404 404 cg 01216 position 65 65
... ... ... ... ... ... ... ...
12569 lastScore-2025-A-1-501 501 cg 01227 position 1 1
12680 lastScore-2025-A-1-500 500 cg 01227 absolute 13622000 13622000
12770 lastScore-2025-A-1-501 501 cg 01227 absolute 13510000 13510000
12881 lastScore-2025-A-1-500 500 cg 01227 relative 112000 112000
12971 lastScore-2025-A-1-501 501 cg 01227 relative 0 0

11142 rows × 7 columns

The absolute and relative times are both in milliseconds, so we can divide those down to provide a more natural time unit of seconds.

# We want the metric values as ints, but we go via a float
melted[["value_0", "value_1"]] = melted[["value_0", "value_1"]].astype(float)
melted.loc[melted["metric"].isin(["absolute", "relative"]), ["value_0", "value_1"]] /= 1000
melted[["value_0", "value_1"]] = melted[["value_0", "value_1"]].astype(int)

melted
_id team.bib type waypoint metric value_0 value_1
0 lastScore-2025-A-1-427 427 cg 01216 position 128 128
1 lastScore-2025-A-1-634 634 cg 01216 position 194 194
2 lastScore-2025-A-1-330 330 cg 01216 position 53 53
3 lastScore-2025-A-1-243 243 cg 01216 position 60 60
4 lastScore-2025-A-1-404 404 cg 01216 position 65 65
... ... ... ... ... ... ... ...
12569 lastScore-2025-A-1-501 501 cg 01227 position 1 1
12680 lastScore-2025-A-1-500 500 cg 01227 absolute 13622 13622
12770 lastScore-2025-A-1-501 501 cg 01227 absolute 13510 13510
12881 lastScore-2025-A-1-500 500 cg 01227 relative 112 112
12971 lastScore-2025-A-1-501 501 cg 01227 relative 0 0

11142 rows × 7 columns

The category and stage indicators are currently embedded in the index value, which has the form lastScore-YEAR-CATEGORY-STAGE-BIB. We could unpack these values to make it easier to structure searches around those conditions.

melted[['year', 'category', 'stage']] = melted['_id'].str.extract(
    r'lastScore-(\d{4})-([A-Z])-([\d]+)')
melted.head()
_id team.bib type waypoint metric value_0 value_1 year category stage
0 lastScore-2025-A-1-427 427 cg 01216 position 128 128 2025 A 1
1 lastScore-2025-A-1-634 634 cg 01216 position 194 194 2025 A 1
2 lastScore-2025-A-1-330 330 cg 01216 position 53 53 2025 A 1
3 lastScore-2025-A-1-243 243 cg 01216 position 60 60 2025 A 1
4 lastScore-2025-A-1-404 404 cg 01216 position 65 65 2025 A 1

We also need to handle the stage start (dss) and end (ce) data.

ce_cols = [col for col in _results.columns if col.startswith('ce')]

melted_ce = _results[[id_column, "team.bib", *ce_cols]].copy()
melted_ce['ce.bonus'] = melted_ce['ce.bonus'].astype(object)
melted_ce.loc[:, "ce.bonus"] = melted_ce['ce.bonus'].apply(lambda x: [x, x])
melted_ce = melted_ce.melt(id_vars=[id_column, "team.bib"]).dropna()

melted_ce = melted_ce[melted_ce['variable'].str.contains('position|absolute|relative`|bonus')]
melted_ce["metric"] = melted_ce["variable"].str.split('.').str[-1]
melted_ce[['value_0', 'value_1']] = pd.DataFrame(
    melted_ce['value'].tolist(),
    index=melted_ce.index
)

melted_ce.drop(columns=["variable", "value"], inplace=True)
melted_ce[["value_0", "value_1"]] = melted_ce[[
    "value_0", "value_1"]].astype(float)
melted_ce.loc[melted_ce["metric"].isin(["absolute", "relative"]), [
    "value_0", "value_1"]] /= 1000
melted_ce[["value_0", "value_1"]] = melted_ce[[
    "value_0", "value_1"]].astype(int)
melted_ce
_id team.bib metric value_0 value_1
0 lastScore-2025-A-1-427 427 position 125 125
1 lastScore-2025-A-1-634 634 position 196 197
2 lastScore-2025-A-1-330 330 position 43 43
3 lastScore-2025-A-1-243 243 position 50 50
4 lastScore-2025-A-1-404 404 position 34 34
... ... ... ... ... ...
799 lastScore-2025-A-1-212 212 bonus 0 0
800 lastScore-2025-A-1-208 208 bonus 0 0
801 lastScore-2025-A-1-313 313 bonus 0 0
802 lastScore-2025-A-1-628 628 bonus 0 0
803 lastScore-2025-A-1-318 318 bonus 0 0

603 rows × 5 columns

dss_cols = [col for col in _results.columns if col.startswith('dss')]

melted_dss = _results[[id_column, "team.bib", *dss_cols]].copy()
melted_dss = melted_dss.melt(id_vars=[id_column, "team.bib"]).dropna()

melted_dss = melted_dss[melted_dss['variable'].str.contains(
    'position|absolute')]
melted_dss["metric"] = melted_dss["variable"].str.split('.').str[-1]

melted_dss.drop(columns=["variable"], inplace=True)
melted_dss["value_0"] = melted_dss["value"].astype(float)
melted_dss.loc[melted_dss["metric"].isin(["absolute"]), [
    "value_0"]] /= 1000
melted_dss["value_0"] = melted_dss[
    "value_0"].astype(int)
melted_dss["value_1"] = melted_dss[
    "value_0"]
melted_dss.drop(columns="value", inplace=True)
melted_dss
_id team.bib metric value_0 value_1
0 lastScore-2025-A-1-427 427 position 130 130
1 lastScore-2025-A-1-634 634 position 171 171
2 lastScore-2025-A-1-330 330 position 55 55
3 lastScore-2025-A-1-243 243 position 67 67
4 lastScore-2025-A-1-404 404 position 72 72
... ... ... ... ... ...
397 lastScore-2025-A-1-212 212 absolute 37020 37020
398 lastScore-2025-A-1-208 208 absolute 34620 34620
399 lastScore-2025-A-1-313 313 absolute 39240 39240
400 lastScore-2025-A-1-628 628 absolute 42630 42630
401 lastScore-2025-A-1-318 318 absolute 40500 40500

402 rows × 5 columns

melted_ce = pd.concat([melted_ce, melted_dss], ignore_index=True)
melted_ce[['year', 'category', 'stage']] = melted_ce['_id'].str.extract(
    r'lastScore-(\d{4})-([A-Z])-([\d]+)')
melted_ce
_id team.bib metric value_0 value_1 year category stage
0 lastScore-2025-A-1-427 427 position 125 125 2025 A 1
1 lastScore-2025-A-1-634 634 position 196 197 2025 A 1
2 lastScore-2025-A-1-330 330 position 43 43 2025 A 1
3 lastScore-2025-A-1-243 243 position 50 50 2025 A 1
4 lastScore-2025-A-1-404 404 position 34 34 2025 A 1
... ... ... ... ... ... ... ... ...
1000 lastScore-2025-A-1-212 212 absolute 37020 37020 2025 A 1
1001 lastScore-2025-A-1-208 208 absolute 34620 34620 2025 A 1
1002 lastScore-2025-A-1-313 313 absolute 39240 39240 2025 A 1
1003 lastScore-2025-A-1-628 628 absolute 42630 42630 2025 A 1
1004 lastScore-2025-A-1-318 318 absolute 40500 40500 2025 A 1

1005 rows × 8 columns