<jupyter_start><jupyter_text>Exploring Marathon Finishing TimesHere we'll look at using Seaborn to help visualize and understand finishing results from a marathon.The data is scrapped from sources on the Web, aggregated it and removed any identifying information, and put it on GitHub where it can be downloaded(if you are interested in using Python for web scraping, I would recommend [*Web Scraping with Python*](http://shop.oreilly.com/product/0636920034391.do) by <NAME>).We will start by downloading the data fromthe Web, and loading it into Pandas:<jupyter_code>!curl -O https://raw.githubusercontent.com/jakevdp/marathon-data/master/marathon-data.csv
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
plt.style.use('classic')
sns.set()


data = pd.read_csv('marathon-data.csv')<jupyter_output><empty_output><jupyter_text>E1. Display the head of the data frame<jupyter_code><jupyter_output><empty_output><jupyter_text>By default, Pandas loaded the time columns as Python strings (type ``object``); we can see this by looking at the ``dtypes`` attribute of the DataFrame:<jupyter_code>data.dtypes<jupyter_output><empty_output><jupyter_text>E.2 Let's fix this by providing a converter for the times:<jupyter_code>import datetime

def convert_time(s):
    h, m, s = map(int, s.split(":"))
    return datetime.timedelta(hours = h, minutes = m, seconds = s)
    return "converted time"

data = pd.read_csv('marathon-data.csv',converters={'split':convert_time, 'final':convert_time})
data.head()
data.dtypes<jupyter_output><empty_output><jupyter_text>E.3 That looks much better. For the purpose of our Seaborn plotting utilities, let's next add columns that give the times in seconds:<jupyter_code>data['split_sec'] = data['split'].astype(int)/1e9
data['final_sec'] = data['split'].astype(int)/1e9

data.head()<jupyter_output><empty_output><jupyter_text>E.3 To get an idea of what the data looks like, we can plot a ``jointplot`` over the data:<jupyter_code>with sns.axes_style('white'):
    g = #
    g.ax_joint.plot(np.linspace(4000, 16000),
                    np.linspace(8000, 32000), ':k')<jupyter_output><empty_output><jupyter_text>The dotted line shows where someone's time would lie if they ran the marathon at a perfectly steady pace. The fact that the distribution lies above this indicates (as you might expect) that most people slow down over the course of the marathon.If you have run competitively, you'll know that those who do the opposite—run faster during the second half of the race—are said to have "negative-split" the race.Let's create another column in the data, the split fraction, which measures the degree to which each runner negative-splits or positive-splits the race: E.4 split_frac = 1 - 2*split_sec/final_sec<jupyter_code>data.head()<jupyter_output><empty_output><jupyter_text>Where this split difference is less than zero, the person negative-split the race by that fraction.Let's do a distribution plot of this split fraction:<jupyter_code># show number of participants with split_frac < 0<jupyter_output><empty_output><jupyter_text>Out of nearly 40,000 participants, there were only 251 people who negative-split their marathon.Let's see whether there is any correlation between this split fraction and other variables. We'll do this using a ``pairgrid``, which draws plots of all these correlations:<jupyter_code><jupyter_output><empty_output><jupyter_text>It looks like the split fraction does not correlate particularly with age, but does correlate with the final time: faster runners tend to have closer to even splits on their marathon time.(We see here that Seaborn is no panacea for Matplotlib's ills when it comes to plot styles: in particular, the x-axis labels overlap. Because the output is a simple Matplotlib plot, however, the methods in [Customizing Ticks](04.10-Customizing-Ticks.ipynb) can be used to adjust such things if desired.)The difference between men and women here is interesting. Let's look at the histogram of split fractions for these two groups:<jupyter_code><jupyter_output><empty_output><jupyter_text>The interesting thing here is that there are many more men than women who are running close to an even split!This almost looks like some kind of bimodal distribution among the men and women. Let's see if we can suss-out what's going on by looking at the distributions as a function of age.A nice way to compare distributions is to use a *violin plot*<jupyter_code><jupyter_output><empty_output><jupyter_text>This is yet another way to compare the distributions between men and women.Let's look a little deeper, and compare these violin plots as a function of age. We'll start by creating a new column in the array that specifies the decade of age that each person is in:age_dec = age //10<jupyter_code><jupyter_output><empty_output><jupyter_text>Looking at this, we can see where the distributions of men and women differ: the split distributions of men in their 20s to 50s show a pronounced over-density toward lower splits when compared to women of the same age (or of any age, for that matter).Also surprisingly, the 80-year-old women seem to outperform *everyone* in terms of their split time. This is probably due to the fact that we're estimating the distribution from small numbers, as there are only a handful of runners in that range:<jupyter_code><jupyter_output><empty_output><jupyter_text>Back to the men with negative splits: who are these runners? Does this split fraction correlate with finishing quickly? We can plot this very easily. We'll use ``regplot``, which will automatically fit a linear regression to the data:<jupyter_code><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07362502196450536, 'fraction_numerical': 0.01107011070110701, 'mean_word_length': 5.68075117370892, 'pattern_counts': {'":': 1, '<': 59, '<?xml version=': 0, '>': 58, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '516642', 'license': 'MIT', 'n_tokens_mistral': 1697, 'n_tokens_neox': 1591, 'n_words': 705, 'path': 'Python_exercise/Exploring_Marathon_Finishing_Times/Exploring_Marathon_Finishing_Times.ipynb', 'repo_name': 'Kaiyang-Liu/Research-Program-in-Business-Analytics', 'size': '5698'}