Table Contest 2024

Author

Stephan Teodosescu

Data Preparation

Code
import pandas as pd
import numpy as np
from importlib_resources import files

# load data
dg_performance = pd.read_csv('https://raw.githubusercontent.com/steodose/Table-Contest-2024/master/dg_performance_2024.csv')

# setting up img file paths for flag icons
#flags_path = '/Users/Stephan/Desktop/Python/Table-Contest/flags/'
flags_path = 'https://raw.githubusercontent.com/steodose/Table-Contest-2024/master/flags/'

# function to replace numeric wins with trophy emojis
def replace_with_emojis(x):
    return '🏆' * int(x) if x > 0 else ''


#### Data preparation ####
selected_columns = [
    'country','player_name', 'tour', 'wins', 'x_wins', 'putt_true', 'arg_true', 
    'app_true', 'ott_true', 't2g_true', 'total_true'
]


dg_clean = dg_performance[selected_columns].replace(-9999, 0) # replace LIV values with 0 values for formatting purposes
dg_clean['player_name'] = dg_clean['player_name'].apply(lambda name: ' '.join(name.split(', ')[::-1])) # fix player naming conventions

# Creating the 'logo' column with the HTML image tag
dg_clean['country'] = '<img height=30 src="' + flags_path + dg_clean['country'] + '.png"></img>'

# apply the emoji function to the 'wins' column before creating the GT table
dg_clean.loc[:, 'wins'] = dg_clean['wins'].apply(lambda x: '🏆' * int(x) if pd.notna(x) and x > 0 else '')


dg_top20 = dg_clean.head(20) # cut off at Top 20
dg_top20.insert(0, 'rank', range(1, 21)) # adding a new column 'rank' which is a simple index + 1 (since index starts at 0)

Generate table using great_tables

Code
from great_tables import GT, md, html

#### ---------- Make GT table ------------- ####
table = GT(dg_top20)
table = table.tab_header(
    title=md("**Scottie Scheffler's Dominance**"),
    subtitle="Evaluating 2024 performance among top professional golfers using Data Golf's true strokes-gained and expected wins (xWins) metrics. Data as of June 9, 2024."
    )
table = table.tab_source_note(
    source_note="Strokes-Gained (SG) is a measure of a player's performance relative to the field average. Putt: Putting, ATG: Around the Green, App: Approach, OTT: Off-the-Tee, TTG: Tee-to-Green"
    )
table = table.tab_source_note(
    source_note=md("**Source:** Data Golf | **Table:** Stephan Teodosescu (@steodosescu)")
    )
table = table.cols_label(
        rank = "Rank",
        country = "Country",
        player_name = "Player",
        tour= "Tour",
        wins = 'Wins', 
        x_wins = 'xWins', 
        putt_true = 'Putt SG', 
        arg_true = 'ATG SG',
        app_true = 'App SG', 
        ott_true = 'OTT SG', 
    t2g_true = 'TTG SG', 
    total_true = 'Total SG'
    )
table = table.tab_spanner(label = md('**Strokes Gained**'),
    columns = ["putt_true", "arg_true", "app_true", "ott_true", "t2g_true", "total_true"]
    )
table = table.fmt_number(
    columns=['putt_true', 'arg_true', 'app_true', 'ott_true', 't2g_true', 'total_true'],
    decimals=2
    )
table = table.fmt_number(
    columns=["x_wins"],
    decimals=1
    )
table = table.cols_width(
    cases={
            "wins": "150px"
        }
    )
# table = table.fmt_number(
#     columns=["wins"],
#     decimals=0
#     )
table = table.data_color(
        columns="x_wins",
        palette=["white", "blue"],
        domain=[0,8]
    )
table = table.data_color(
        columns=['putt_true', 'arg_true', 'app_true', 'ott_true', 't2g_true', 'total_true'],
        palette=["white", "orange"],
        domain=[-2,4]
    )
table = table.tab_options(
        heading_title_font_size = '30px',
        heading_subtitle_font_size= '16px',
        heading_background_color="black",
        table_background_color = "white"
        #,container_width='1100px'
        #,table_width = '600px'
    )

# display table
table
Scottie Scheffler's Dominance
Evaluating 2024 performance among top professional golfers using Data Golf's true strokes-gained and expected wins (xWins) metrics. Data as of June 9, 2024.
Rank Country Player Tour Wins xWins Strokes Gained
Putt SG ATG SG App SG OTT SG TTG SG Total SG
1 Scottie Scheffler PGA 🏆🏆🏆🏆🏆 4.1 0.22 0.63 1.66 1.04 3.33 3.44
2 Xander Schauffele PGA 🏆 2.2 0.75 0.40 0.93 0.85 2.18 2.76
3 Rory McIlroy PGA 🏆🏆🏆 1.4 0.40 0.20 0.66 1.01 1.87 2.23
4 Ludvig Aberg PGA 0.5 0.45 0.03 0.77 0.72 1.51 1.98
5 Collin Morikawa PGA 1.0 0.17 0.47 0.59 0.67 1.74 1.91
6 Louis Oosthuizen LIV 🏆🏆 0.3 0.00 0.00 0.00 0.00 0.00 1.85
7 Joaquin Niemann LIV 🏆🏆🏆 0.6 −0.45 0.40 1.19 0.54 2.13 1.81
8 Bryson DeChambeau LIV 0.0 0.80 0.38 0.88 1.71 2.97 1.76
9 Jon Rahm LIV 0.0 −0.60 0.54 0.22 0.02 0.78 1.66
10 Hideki Matsuyama PGA 🏆 1.3 −0.12 0.76 0.63 0.36 1.75 1.55
11 Justin Thomas PGA 0.2 −0.33 0.54 0.91 0.37 1.81 1.54
12 Sahith Theegala PGA 0.5 0.56 −0.14 0.59 0.62 1.07 1.54
13 Christiaan Bezuidenhout PGA 0.5 0.78 0.23 0.62 −0.04 0.80 1.51
14 Alex Noren PGA 0.0 0.29 0.41 0.42 0.28 1.11 1.42
15 Tommy Fleetwood PGA 🏆 0.2 0.30 0.48 0.26 0.36 1.10 1.42
16 Russell Henley PGA 0.1 0.42 0.39 0.50 0.16 1.05 1.41
17 Wyndham Clark PGA 🏆 2.0 0.28 0.10 0.42 0.68 1.21 1.41
18 Sam Burns PGA 0.4 0.36 0.10 0.32 0.44 0.87 1.40
19 Dean Burmester LIV 🏆🏆🏆 0.3 0.01 0.72 1.30 0.52 2.54 1.37
20 Byeong Hun An PGA 0.7 0.06 0.11 0.51 0.66 1.28 1.32
Strokes-Gained (SG) is a measure of a player's performance relative to the field average. Putt: Putting, ATG: Around the Green, App: Approach, OTT: Off-the-Tee, TTG: Tee-to-Green
Source: Data Golf | Table: Stephan Teodosescu (@steodosescu)