Paris Olympics 2024 Medal standings

Paris Olympics have been real inspiration on so many levels. There is probably no athlete at this Olympics who does not prepare for it every day for 6-8 hours for their few minutes of fame. To see dedication and commitment of that sort is simply awe-inspiring.

I crunched some numbers on Olympics medal standings. A big congratulations to Georgia ๐Ÿ‡ฌ๐Ÿ‡ช for delivering the best performance relative to their resources, and New Zealand ๐Ÿ‡ฆ๐Ÿ‡บ for earning the highest number of medals per capita!

Data sources for medals (https://lnkd.in/gHCTqBCD) and country stats for 2023 (https://lnkd.in/ggpCHi_i).

This is not much different then Tokyo 2020:

!pip install pandas dataframe-image
Requirement already satisfied: pandas in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (2.2.2)
Requirement already satisfied: dataframe-image in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (0.2.4)
Requirement already satisfied: numpy>=1.22.4 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from pandas) (1.26.4)
Requirement already satisfied: python-dateutil>=2.8.2 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from pandas) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from pandas) (2024.1)
Requirement already satisfied: tzdata>=2022.7 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from pandas) (2024.1)
Requirement already satisfied: nbconvert>=5 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (7.16.4)
Requirement already satisfied: aiohttp in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (3.10.3)
Requirement already satisfied: requests in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (2.31.0)
Requirement already satisfied: pillow in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (10.3.0)
Requirement already satisfied: packaging in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (24.0)
Requirement already satisfied: mistune in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (3.0.2)
Requirement already satisfied: lxml in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (5.3.0)
Requirement already satisfied: beautifulsoup4 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (4.12.3)
Requirement already satisfied: cssutils in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (2.11.1)
Requirement already satisfied: html2image in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (2.0.4.3)
Requirement already satisfied: cssselect in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from dataframe-image) (1.2.0)
Requirement already satisfied: bleach!=5.0.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (6.1.0)
Requirement already satisfied: defusedxml in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (0.7.1)
Requirement already satisfied: jinja2>=3.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (3.1.3)
Requirement already satisfied: jupyter-core>=4.7 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (5.7.2)
Requirement already satisfied: jupyterlab-pygments in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (0.3.0)
Requirement already satisfied: markupsafe>=2.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (2.1.5)
Requirement already satisfied: nbclient>=0.5.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (0.10.0)
Requirement already satisfied: nbformat>=5.7 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (5.10.4)
Requirement already satisfied: pandocfilters>=1.4.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (1.5.1)
Requirement already satisfied: pygments>=2.4.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (2.17.2)
Requirement already satisfied: tinycss2 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (1.3.0)
Requirement already satisfied: traitlets>=5.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbconvert>=5->dataframe-image) (5.14.3)
Requirement already satisfied: six>=1.5 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)
Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (2.3.5)
Requirement already satisfied: aiosignal>=1.1.2 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (1.3.1)
Requirement already satisfied: attrs>=17.3.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (24.2.0)
Requirement already satisfied: frozenlist>=1.1.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (1.4.1)
Requirement already satisfied: multidict<7.0,>=4.5 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (6.0.5)
Requirement already satisfied: yarl<2.0,>=1.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (1.9.4)
Requirement already satisfied: async-timeout<5.0,>=4.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from aiohttp->dataframe-image) (4.0.3)
Requirement already satisfied: soupsieve>1.2 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from beautifulsoup4->dataframe-image) (2.5)
Requirement already satisfied: more-itertools in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from cssutils->dataframe-image) (10.4.0)
Requirement already satisfied: websocket-client<2.0.0,>=1.0.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from html2image->dataframe-image) (1.8.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from requests->dataframe-image) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from requests->dataframe-image) (3.7)
Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from requests->dataframe-image) (2.2.1)
Requirement already satisfied: certifi>=2017.4.17 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from requests->dataframe-image) (2024.2.2)
Requirement already satisfied: webencodings in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from bleach!=5.0.0->nbconvert>=5->dataframe-image) (0.5.1)
Requirement already satisfied: platformdirs>=2.5 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from jupyter-core>=4.7->nbconvert>=5->dataframe-image) (4.2.0)
Requirement already satisfied: jupyter-client>=6.1.12 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbclient>=0.5.0->nbconvert>=5->dataframe-image) (8.6.1)
Requirement already satisfied: fastjsonschema>=2.15 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbformat>=5.7->nbconvert>=5->dataframe-image) (2.20.0)
Requirement already satisfied: jsonschema>=2.6 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from nbformat>=5.7->nbconvert>=5->dataframe-image) (4.23.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert>=5->dataframe-image) (2023.12.1)
Requirement already satisfied: referencing>=0.28.4 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert>=5->dataframe-image) (0.35.1)
Requirement already satisfied: rpds-py>=0.7.1 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert>=5->dataframe-image) (0.20.0)
Requirement already satisfied: pyzmq>=23.0 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from jupyter-client>=6.1.12->nbclient>=0.5.0->nbconvert>=5->dataframe-image) (26.0.1)
Requirement already satisfied: tornado>=6.2 in /Users/nenadbozinovic/Projects/blog/venv/lib/python3.10/site-packages (from jupyter-client>=6.1.12->nbclient>=0.5.0->nbconvert>=5->dataframe-image) (6.4)

[notice] A new release of pip is available: 24.0 -> 24.2
[notice] To update, run: pip install --upgrade pip
import pandas as pd
import dataframe_image as dfi

# Load the medal standings and world data
medal_standings = pd.read_csv('paris_2024_olympics_full_medal_standings_final.csv')
world_data = pd.read_csv('world-data-2023.csv')

# Assuming 'Country' is the column to join on in both datasets
merged_data = pd.merge(medal_standings, world_data, on='Country', how='left')

population_str = 'Population (in M)'
GDP_str =  'GDP (in $B)'

medals_per_million_people_str = 'Total medals per 1M capita'
medals_per_gdp = 'Total medals per $1B GDP'

merged_data = merged_data.dropna(subset=['Population', 'GDP'])
# Remove dollar signs and commas from the 'GDP' column, then convert to float

merged_data.rename(columns={'Total': 'Total medals'}, inplace=True) 

medals_str = 'Total medals'

merged_data[GDP_str] = merged_data['GDP'].replace({r'\$': '', ',': ''}, regex=True).astype(float) / 10**9
merged_data[population_str] = merged_data['Population'].replace({',': ''}, regex=True).astype(float) / 10**6

merged_data[medals_per_million_people_str] = merged_data[medals_str] / merged_data[population_str]
merged_data[medals_per_gdp] = merged_data[medals_str] / merged_data[GDP_str]


def sort_by_column(column_name, column_name2=None):

    # Sort the DataFrame by the 'Medals per 1M capita' in descending order
    sorted_data = merged_data.sort_values(by=column_name, ascending=False)
    

    final_table = sorted_data[['Country', 'Total medals'] + ([column_name2] if column_name2 else [])].reset_index(drop=True).head(10)
    
    final_table = final_table.round(2)
    
    # Create a new DataFrame with only 'Country' and 'Medals per 1M capita'
    final_table.index = final_table.index + 1
    
            # Style the DataFrame to add borders
    styled_final_table = final_table.style.set_table_styles(
    [{'selector': 'th',
      'props': [('border', '2px solid black')]},
     {'selector': 'td',
      'props': [('border', '1px solid black')]},
     {'selector': 'table',
      'props': [('border', '10px solid black')]}]
).format(precision=2)

    # Save the table as a PNG file
    dfi.export(styled_final_table, f'final_table_{column_name}.png')

    # Optionally, you can print the top 10 rows to inspect
    return final_table
merged_data.head(50)
Rank Country Gold Silver Bronze Total medals Density\n(P/Km2) Abbreviation Agricultural Land( %) Land Area(Km2) ... Tax revenue (%) Total tax rate Unemployment rate Urban_population Latitude Longitude GDP (in $B) Population (in M) Total medals per 1M capita Total medals per $1B GDP
0 1 United States 40 44 42 126 36 US 44.40% 9,833,517 ... 9.60% 36.60% 14.70% 270,663,028 37.090240 -95.712891 21427.700000 328.239523 0.383866 0.005880
1 2 China 40 27 24 91 153 CN 56.20% 9,596,960 ... 9.40% 59.20% 4.32% 842,933,962 35.861660 104.195397 19910.000000 1397.715000 0.065106 0.004571
2 3 Japan 20 12 13 45 347 JP 12.30% 377,944 ... 11.90% 46.70% 2.29% 115,782,416 36.204824 138.252924 5081.769542 126.226568 0.356502 0.008855
3 4 Australia 18 19 16 53 3 AU 48.20% 7,741,220 ... 23.00% 47.40% 5.27% 21,844,756 -25.274398 133.775136 1392.680589 25.766605 2.056926 0.038056
4 5 France 16 26 22 64 119 FR 52.40% 643,801 ... 24.20% 60.70% 8.43% 54,123,364 46.227638 2.213749 2715.518274 67.059887 0.954371 0.023568
5 6 Netherlands 15 7 12 34 508 NL 53.30% 41,543 ... 23.00% 41.20% 3.20% 15,924,729 52.132633 5.291266 909.070395 17.332850 1.961593 0.037401
7 8 South Korea 13 9 10 32 527 KR 17.40% 99,720 ... 15.60% 33.20% 4.15% 42,106,719 35.907757 127.766922 2029.000000 51.709098 0.618847 0.015771
8 9 Italy 12 13 15 40 206 IT 43.20% 301,340 ... 24.30% 59.10% 9.89% 42,651,966 41.871940 12.567380 2001.244392 60.297396 0.663379 0.019988
9 10 Germany 12 13 8 33 240 DE 47.70% 357,022 ... 11.50% 48.80% 3.04% 64,324,835 51.165691 10.451526 3845.630031 83.132799 0.396955 0.008581
10 11 New Zealand 10 7 3 20 18 NZ 40.50% 268,838 ... 29.00% 34.60% 4.07% 4,258,860 -40.900557 174.885971 206.928766 4.841000 4.131378 0.096652
11 12 Canada 9 7 11 27 4 CA 6.90% 9,984,670 ... 12.80% 24.50% 5.56% 30,628,482 56.130366 -106.346771 1736.425630 36.991981 0.729888 0.015549
12 13 Uzbekistan 8 2 3 13 79 UZ 62.90% 447,400 ... 14.80% 31.60% 5.92% 16,935,729 41.377491 64.585262 57.921286 33.580650 0.387128 0.224443
13 14 Hungary 6 7 6 19 107 HU 58.40% 93,028 ... 23.00% 37.90% 3.40% 6,999,582 47.162494 19.503304 160.967158 9.769949 1.944739 0.118037
14 15 Spain 5 4 9 18 94 ES 52.60% 505,370 ... 14.20% 47.00% 13.96% 37,927,409 40.463667 -3.749220 1394.116311 47.076781 0.382354 0.012911
15 16 Sweden 4 4 3 11 25 SE 7.40% 450,295 ... 27.90% 49.10% 6.48% 9,021,165 60.128161 18.643501 530.832909 10.285453 1.069472 0.020722
16 17 Kenya 4 2 5 11 94 KE 48.50% 580,367 ... 15.10% 37.20% 2.64% 14,461,523 -0.023559 37.906193 95.503089 52.573973 0.209229 0.115180
17 18 Norway 4 1 3 8 15 NO 2.70% 323,802 ... 23.90% 36.20% 3.35% 4,418,218 60.472024 8.468946 403.336364 5.347896 1.495915 0.019835
19 20 Brazil 3 7 10 20 25 BR 33.90% 8,515,770 ... 14.20% 65.10% 12.08% 183,241,641 -14.235004 -51.925280 1839.758041 212.559417 0.094091 0.010871
20 21 Iran 3 6 3 12 52 IR 28.20% 1,648,195 ... 7.40% 44.70% 11.38% 62,509,623 32.427908 53.688046 445.345282 82.913906 0.144728 0.026945
21 22 Ukraine 3 5 4 12 75 UA 71.70% 603,550 ... 20.10% 45.20% 8.88% 30,835,699 48.379433 31.165580 153.781069 44.385155 0.270361 0.078033
22 23 Romania 3 4 2 9 84 RO 58.80% 238,391 ... 14.60% 20.00% 3.98% 10,468,793 45.943161 24.966760 250.077444 19.356544 0.464959 0.035989
23 24 Georgia 3 3 1 7 57 GE 34.50% 69,700 ... 21.70% 9.90% 14.40% 2,196,476 42.315407 43.356892 17.743196 3.720382 1.881527 0.394517
24 25 Belgium 3 1 6 10 383 BE 44.60% 30,528 ... 24.00% 55.40% 5.59% 11,259,082 50.503887 4.469936 529.606710 11.484055 0.870773 0.018882
25 26 Bulgaria 3 1 3 7 64 BG 46.30% 110,879 ... 20.20% 28.30% 4.34% 5,256,027 42.733883 25.485830 86.000000 6.975761 1.003475 0.081395
26 27 Serbia 3 1 1 5 100 RS 39.30% 77,474 ... 18.60% 36.60% 12.69% 3,907,243 44.016521 21.005859 51.409167 6.944975 0.719945 0.097259
27 28 Czech Republic 3 0 2 5 139 CZ 45.20% 78,867 ... 14.90% 46.10% 1.93% 7,887,156 49.817492 15.472962 246.489245 10.669709 0.468616 0.020285
28 29 Denmark 2 2 5 9 137 DK 62.00% 43,094 ... 32.40% 23.80% 4.91% 5,119,978 56.263920 9.501785 348.078018 5.818553 1.546776 0.025856
29 30 Azerbaijan 2 2 3 7 123 AZ 57.70% 86,600 ... 13.00% 40.70% 5.51% 5,616,165 40.143105 47.576927 39.207000 10.023318 0.698372 0.178540
30 31 Croatia 2 2 6 7 73 HR 27.60% 56,594 ... 22.00% 20.50% 6.93% 2,328,318 45.100000 15.200000 60.415553 4.067500 1.720959 0.115864
31 32 Cuba 2 1 1 4 106 CU 59.90% 110,860 ... NaN NaN 1.64% 8,739,135 21.521757 -77.781167 100.023000 11.333483 0.352937 0.039991
32 33 Bahrain 2 1 0 3 2,239 BH 11.10% 765 ... 4.20% 13.80% 0.71% 1,467,109 26.066700 50.557700 38.574069 1.501635 1.997822 0.077772
33 34 Slovenia 2 0 5 7 103 SI 30.70% 20,273 ... 18.60% 31.00% 4.20% 1,144,654 46.151241 14.995463 53.742160 2.087946 3.352577 0.130252
35 36 Austria 2 0 2 4 109 AT 32.40% 83,871 ... 25.40% 51.40% 4.67% 5,194,416 47.516231 14.550072 446.314740 8.877067 0.450599 0.008962
37 38 Philippines 2 0 1 3 368 PH 41.70% 300,000 ... 14.00% 43.10% 2.15% 50,975,903 12.879721 121.774017 376.795509 108.116615 0.027748 0.007962
38 39 Algeria 2 0 1 3 18 DZ 17.40% 2,381,741 ... 37.20% 66.10% 11.70% 31,510,100 28.033886 1.659626 169.988236 43.053054 0.069681 0.017648
39 40 Indonesia 1 5 1 7 151 ID 31.50% 1,904,569 ... 10.20% 30.10% 4.69% 151,509,724 -0.789275 113.921327 1119.190781 270.203917 0.025906 0.006255
40 41 Israel 1 4 5 10 400 IL 24.60% 20,770 ... 23.10% 25.30% 3.86% 8,374,393 31.046051 34.851612 395.098666 9.053300 1.104570 0.025310
41 42 Poland 1 3 3 7 124 PL 46.90% 312,685 ... 17.40% 40.80% 3.47% 22,796,574 51.919438 19.145136 592.164401 37.970874 0.184352 0.011821
42 43 Kazakhstan 1 3 2 6 7 KZ 80.40% 2,724,900 ... 11.70% 28.40% 4.59% 10,652,915 48.019573 66.923684 180.161741 18.513930 0.324080 0.033303
43 44 Jamaica 1 3 2 6 273 JM 41.00% 10,991 ... 26.80% 35.10% 8.00% 1,650,594 18.109581 -77.297508 16.458071 2.948279 2.035086 0.364563
44 45 South Africa 1 3 1 5 49 ZA 79.80% 1,219,090 ... 27.50% 29.20% 28.18% 39,149,717 -30.559482 22.937506 351.431649 58.558270 0.085385 0.014228
45 46 Thailand 1 2 1 4 137 TH 43.30% 513,120 ... 14.90% 29.50% 0.75% 35,294,600 15.870032 100.992541 543.649976 69.625582 0.057450 0.007358
47 48 Ethiopia 1 2 1 4 115 ET 36.30% 1,104,300 ... 7.50% 37.70% 2.08% 23,788,710 9.145000 40.489673 96.107662 112.078730 0.035689 0.041620
48 49 Switzerland 1 2 1 4 219 CH 38.40% 41,277 ... 10.10% 28.80% 4.58% 6,332,428 46.818188 8.227512 703.082435 8.574832 0.466481 0.005689
49 50 Turkey 1 2 1 4 110 TR 49.80% 783,562 ... 17.90% 42.30% 13.49% 63,097,818 38.963745 35.243322 754.411708 83.429615 0.047945 0.005302
50 51 Argentina 1 1 1 3 17 AR 54.30% 2,780,400 ... 10.10% 106.30% 9.79% 41,339,571 -38.416097 -63.616672 449.663447 44.938712 0.066758 0.006672

46 rows ร— 44 columns

sort_by_column(column_name=GDP_str)
Country Total medals
1 United States 126
2 China 91
3 Japan 45
4 Germany 33
5 France 64
6 South Korea 32
7 Italy 40
8 Brazil 20
9 Canada 27
10 Spain 18
sort_by_column(column_name=medals_per_million_people_str, column_name2=population_str)
Country Total medals Population (in M)
1 New Zealand 20 4.84
2 Slovenia 7 2.09
3 Australia 53 25.77
4 Jamaica 6 2.95
5 Bahrain 3 1.50
6 Netherlands 34 17.33
7 Hungary 19 9.77
8 Georgia 7 3.72
9 Croatia 7 4.07
10 Denmark 9 5.82
sort_by_column(column_name=medals_per_gdp, column_name2=GDP_str)
Country Total medals GDP (in $B)
1 Georgia 7 17.74
2 Jamaica 6 16.46
3 Uzbekistan 13 57.92
4 Azerbaijan 7 39.21
5 Slovenia 7 53.74
6 Hungary 19 160.97
7 Croatia 7 60.42
8 Kenya 11 95.50
9 Serbia 5 51.41
10 New Zealand 20 206.93