# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: 'Python 3.8.6 64-bit (''venv'': venv)'
#     metadata:
#       interpreter:
#         hash: 1dd613a0944e0ee4877c49f3f7544f0058632aedafee0ea9352026a66388253a
#     name: python3
# ---

# # Olympic Games Exploratory Data Analysis

# Before we begin, let's set up some useful settings:
# - Max number of columns to be displayed = 100
# - Max number of columns to be displayed = 100

# +
import pandas as pd

pd.set_option('display.max_columns', 100) 
pd.set_option('display.max_rows', 100) 
# -

# ### First step: read and glimpse the dataset
#
# In this EDA, we'll use the ["120 years of Olympic history: athletes and results"](https://www.kaggle.com/heesoo37/120-years-of-olympic-history-athletes-and-results) Kaggle dataset, locally available in this repo in  `raw_data\athlete_events.csv` . 
#
# Let's first read the dataset:

df = pd.read_csv("raw_data/athlete_events.csv")

# ### Q0: How many rows and columns are there in this dataset?
#

print(df.shape)

# Over 271 thousand competitors in the last 120 years of Olympics! Wow!
#
#

# Let's get some basic info on the available data:

print(df.info())

# Lots of infos available! Let's take a glimpse on actual data:

df.head()

# Each row represents a competitor in a specific event from a specific olympic games. Interesting, very interesting.

# ### Q1: Which are the oldest olympic summer and winter games with data available in the dataset?
#
# To solve this one, we may resort to the `np.sort()` function:
#

# +
import numpy as np

np.sort(df['Year'].unique()) # .unique() to return only one ocurrence for each olympic year
# -

# The first olympic game with data available is actually the first one in modern age, 1896 Olympic Summer games, in Athens. 
#
#

# ### Q2: Which game had the greatest number of registered competitors?
#
# To answer this one, we may resort to `df.value_counts()` :

df['Year'].value_counts()

# Well, the one with greatest number of competitors was not one of the last ones, but rather the 1992 Summer Games! Very interesting!
#
#

# ### Q3.1: What is the range of competing athletes' age?
#
# This one is rather simple:

# +
import numpy as np

min_age_all_sports = np.amin(df['Age'])

max_age_all_sports = np.amax(df['Age'])

print(f'Age ranging from {min_age_all_sports} to {max_age_all_sports}')
# -

# ### Q3.2: What is the most common athlete age found in games?
#
# One could guess that most athletes are young, in their finest physical forms. But is this true? Let's find out.

df.groupby(by="Age")["Age"].count().sort_values(ascending=False).head()

# Interesting! Most common age is 23 years old, followed by ages in twenties range. But is the age spread or tightly concentrade around this value?
#

df["Age"].describe() # display all major statistics (mean, median, std, quartiles) at once

# Well, indeed, most athletes (75%) had 28 or less years while competing. The youngest of all was a 10-year old child! And the oldest one was a 97-year old senior! Impressive!
#
# Is Age "evenly distributed", in the sense of being not side-skewed or not too spiked  /flatted? We can quickly glance this by looking at its kurtosis and skewness values.

df["Age"].skew() # retrieve its skewness

# So, as Age distribution has a positive skewness, it is right-skewed, i.e. skewed towards the right, having its most common value (mode), mean and median all concentrated in the left side, with a long tail to the right

df["Age"].kurt() # retrieve its kurtosis

# As Age distribution has a kurtosis > 3, it is leptokurtic, i.e. a little "spikier" than normal distribution, with more mass concentrated around its central values (mean, median, mode).
#
# By only looking at its kurtosis and skewness, we found Age distritubion is assymetric to the left (i.e. with smaller values of Age being more common) and "spikier" (i.e. much concentrated around mean, median and mode). If are a "seeing is believing" kind of person, let's make a simple histogram/distribution graph to confirm it:

# +
import seaborn as sns

sns.displot(df["Age"], discrete=True)
# -

# Just as we have found previously!
#
# So, this brief analysis confirm that, in general, most athletes are very young while competing, relying in their finest physical forms to complete most sports' events. 
#
# But.. does this result hold for most sports? Is there a sport where seniors compete most? We shall see this one next. But first, one may ask: is medal-winners Age distribution any how similar to the general athlete distribution? Let's find out.

df.query('Medal in ("Gold", "Silver", "Bronze")')["Age"].describe()

print(df.query('Medal in ("Gold", "Silver", "Bronze")')["Age"].kurt())
print(df.query('Medal in ("Gold", "Silver", "Bronze")')["Age"].skew())

# So, winners' distribution is quite similar, assimetric to the left and spikier, but less so. We can check this in its distribution plot.

sns.displot(df.query('Medal in ("Gold", "Silver", "Bronze")')["Age"], discrete=True)

# Its form is very similar, see? OK, it's not that easy to see just looking at each graph. Let's plot them overlapped.

# +
mod_df = df.assign(Medallist=["Yes" if Medal in ("Gold", "Silver", "Bronze") else "No" for Medal in df.Medal ])[["Age", "Medallist"]] # compute a new column "Medallist" telling if athlete was or not a medalist (regardless of whic medal it achieved)


sns.displot(mod_df, x="Age", hue ="Medallist", discrete=True) 
# -

# Now, you see! Medallists' and non-medalists' Age distribution is very similar, with Medallist much less frequent (of course).

# ### Q3.3: What is the distribution of age in various sports?
#
# Now, to answer this one, we must look not only at the most common value, but also other meaningful statistics of Age attribute in various sports. Let's start with the usual `describe` method:

df[['Age', 'Sport']].groupby('Sport').describe()

# Looking at table above, we see some interesting facts:
# * Rhythmic Gymnastics is a clear outlier with youger athletes - its 75th-percentile is 20 years old!
# * Shooting, Polo, Equestrianism, Croquet, Alpinism, Art Competitions, Roque are outliers with older athletes - their 75th-percentile are 39, 39, 40, 42.5, 47.5, 54, 61.5 years old, respectively!
# * More popular team sports like Football (Soccer), Volleyball, Basketball are very alike and aligned with general statistics - their 75th-percentile are 26, 28, 28 years old, respectively
#
#
# To better see the relationship, let's plot some of the above cited sports.

# +
sports_df = df.query(' Sport in ("Croquet", "Alpinism", "Roque") ')[['Age', 'Sport']] # selecting less popular sports together, to not distort graph with very different count scales

sns.displot(sports_df, x="Age", hue ="Sport", discrete=True) 

# +
sports_df = df.query(' Sport in ("Rhythmic Gymnastics", "Equestrianism") ')[['Age', 'Sport']] # selecting somewhat popular sports, to not distort graph with very different count scales

sns.displot(sports_df, x="Age", hue ="Sport", discrete=True) 

# +
sports_df = df.query(' Sport in ("Football", "Volleyball", "Basketball") ')[['Age', 'Sport']] # selecting very popular sports, to not distort graph with very different count scales

sns.displot(sports_df, x="Age", hue ="Sport", discrete=True) 
# -

# Now, it's important to note that some sports may have policies restricting teams mainly to youger athletes. This is indeed the case of Football, which has a policy restricting the number of athletes with more than 23 years, which clearly reflects in its above graph.

StarcoderdataJupyterScriptsDedupFiltered