{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Data Engineering of Understat Data\n",
"##### Notebook to engineer raw data scraped from [Understat](https://understat.com/).\n",
"\n",
"### By [Edd Webster](https://www.twitter.com/eddwebster)\n",
"Notebook first written: 01/09/2020 \n",
"Notebook last updated: 26/12/2020\n",
"\n",
"![title](../../img/understat-logo-banner.png)\n",
"\n",
"Click [here](#section5) to jump straight to the Exploratory Data Analysis section and skip the [Task Brief](#section2), [Data Sources](#section3), and [Data Engineering](#section4) sections. Or click [here](#section6) to jump straight to the Conclusion."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"___\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Introduction \n",
"This notebook engineers scraped data for shooting from [Understat](https://understat.com/) using [pandas](http://pandas.pydata.org/) for data maniuplation through DataFrames.\n",
"\n",
"For more information about this notebook and the author, I'm available through all the following channels:\n",
"* [eddwebster.com](https://www.eddwebster.com/);\n",
"* edd.j.webster@gmail.com;\n",
"* [@eddwebster](https://www.twitter.com/eddwebster);\n",
"* [linkedin.com/in/eddwebster](https://www.linkedin.com/in/eddwebster/);\n",
"* [github/eddwebster](https://github.com/eddwebster/);\n",
"* [public.tableau.com/profile/edd.webster](https://public.tableau.com/profile/edd.webster);\n",
"* [kaggle.com/eddwebster](https://www.kaggle.com/eddwebster); and\n",
"* [hackerrank.com/eddwebster](https://www.hackerrank.com/eddwebster).\n",
"\n",
"![title](../../img/fifa21eddwebsterbanner.png)\n",
"\n",
"The accompanying GitHub repository for this notebook can be found [here](https://github.com/eddwebster/fifa-league) and a static version of this notebook can be found [here](https://nbviewer.jupyter.org/github/eddwebster/fifa-league/blob/master/FIFA%2020%20Fantasy%20Football%20League%20using%20TransferMarkt%20Player%20Valuations.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"___\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Notebook Contents \n",
"1. [Notebook Dependencies](#section1) \n",
"2. [Project Brief](#section2) \n",
"3. [Data Sources](#section3) \n",
" 1. [Introduction](#section3.1) \n",
" 2. [Data Dictionary](#section3.2) \n",
" 3. [Creating the DataFrame](#section3.3) \n",
" 4. [Initial Data Handling](#section3.4) \n",
" 5. [Export the Raw DataFrame](#section3.5) \n",
"4. [Data Engineering](#section4) \n",
" 1. [Introduction](#section4.1) \n",
" 2. [Columns of Interest](#section4.2) \n",
" 3. [String Cleaning](#section4.3) \n",
" 4. [Converting Data Types](#section4.4) \n",
" 5. [Export the Engineered DataFrame](#section4.5) \n",
"5. [Summary](#section5) \n",
"6. [Next Steps](#section6) \n",
"7. [Bibliography](#section7) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"___\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Notebook Dependencies "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook was written using [Python 3](https://docs.python.org/3.7/) and requires the following libraries:\n",
"* [`Jupyter notebooks`](https://jupyter.org/) for this notebook environment with which this project is presented;\n",
"* [`NumPy`](http://www.numpy.org/) for multidimensional array computing;\n",
"* [`pandas`](http://pandas.pydata.org/) for data analysis and manipulation;\n",
"* `tqdm` for a clean progress bar;\n",
"* `requests` for executing HTTP requests;\n",
"* [`Beautifulsoup`](https://pypi.org/project/beautifulsoup4/) for web scraping; and\n",
"* [`matplotlib`](https://matplotlib.org/contents.html?v=20200411155018) for data visualisations;\n",
"\n",
"All packages used for this notebook except for BeautifulSoup can be obtained by downloading and installing the [Conda](https://anaconda.org/anaconda/conda) distribution, available on all platforms (Windows, Linux and Mac OSX). Step-by-step guides on how to install Anaconda can be found for Windows [here](https://medium.com/@GalarnykMichael/install-python-on-windows-anaconda-c63c7c3d1444) and Mac [here](https://medium.com/@GalarnykMichael/install-python-on-mac-anaconda-ccd9f2014072), as well as in the Anaconda documentation itself [here](https://docs.anaconda.com/anaconda/install/)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Import Libraries and Modules"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Setup Complete\n"
]
}
],
"source": [
"# Python ≥3.5 (ideally)\n",
"import platform\n",
"import sys, getopt\n",
"assert sys.version_info >= (3, 5)\n",
"import csv\n",
"\n",
"# Import Dependencies\n",
"%matplotlib inline\n",
"\n",
"# Math Operations\n",
"import numpy as np\n",
"from math import pi\n",
"\n",
"# Datetime\n",
"import datetime\n",
"from datetime import date\n",
"import time\n",
"\n",
"# Data Preprocessing\n",
"import pandas as pd # version 1.0.3\n",
"import os # used to read the csv filenames\n",
"import re\n",
"import random\n",
"from io import BytesIO\n",
"from pathlib import Path\n",
"\n",
"# Reading directories\n",
"import glob\n",
"import os\n",
"\n",
"# Working with JSON\n",
"import json\n",
"from pandas.io.json import json_normalize\n",
"\n",
"# Web Scraping\n",
"import requests\n",
"from bs4 import BeautifulSoup\n",
"import re\n",
"\n",
"# Fuzzy Matching - Record Linkage\n",
"import recordlinkage\n",
"import jellyfish\n",
"import numexpr as ne\n",
"\n",
"# Data Visualisation\n",
"import matplotlib as mpl\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"plt.style.use('seaborn-whitegrid')\n",
"import missingno as msno # visually display missing data\n",
"\n",
"# Progress Bar\n",
"from tqdm import tqdm # a clean progress bar library\n",
"\n",
"# Display in Jupyter\n",
"from IPython.display import Image, YouTubeVideo\n",
"from IPython.core.display import HTML\n",
"\n",
"# Ignore Warnings\n",
"import warnings\n",
"warnings.filterwarnings(action=\"ignore\", message=\"^internal gelsd\")\n",
"\n",
"print('Setup Complete')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Python: 3.7.6\n",
"NumPy: 1.18.1\n",
"pandas: 1.0.1\n",
"matplotlib: 3.1.3\n",
"Seaborn: 0.10.0\n"
]
}
],
"source": [
"# Python / module versions used here for reference\n",
"print('Python: {}'.format(platform.python_version()))\n",
"print('NumPy: {}'.format(np.__version__))\n",
"print('pandas: {}'.format(pd.__version__))\n",
"print('matplotlib: {}'.format(mpl.__version__))\n",
"print('Seaborn: {}'.format(sns.__version__))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Defined Variables"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# Define today's date\n",
"today = datetime.datetime.now().strftime('%d/%m/%Y').replace('/', '')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Defined Filepaths"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Set up initial paths to subfolders\n",
"base_dir = os.path.join('..', '..', )\n",
"data_dir = os.path.join(base_dir, 'data')\n",
"data_dir_fbref = os.path.join(base_dir, 'data', 'fbref')\n",
"data_dir_tm = os.path.join(base_dir, 'data', 'tm')\n",
"data_dir_understat = os.path.join(base_dir, 'data', 'understat')\n",
"img_dir = os.path.join(base_dir, 'img')\n",
"fig_dir = os.path.join(base_dir, 'img', 'fig')\n",
"video_dir = os.path.join(base_dir, 'video')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Notebook Settings"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"pd.set_option('display.max_columns', None)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Project Brief \n",
"This Jupyter notebook explores how to engineer football shooting data from [Understat](https://understat.com/), using [pandas](http://pandas.pydata.org/) for data maniuplation through DataFrames.\n",
"\n",
"The data of player values produced in this notebook is exported to CSV. This data can be further analysed in Python, joined to other datasets, or explored using Tableau, PowerBI, Microsoft Excel."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Data Sources "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.1. Introduction \n",
"[Understat](https://understat.com/) is a data stats website which is a great source of shooting data including the positions of shots, dating back to the 14/15 season.\n",
"\n",
"Before conducting our EDA, the data needs to be imported as a DataFrame in the Data Sources section [Section 3](#section3) and Cleaned in the Data Engineering section [Section 4](#section4).\n",
"\n",
"We'll be using the [pandas](http://pandas.pydata.org/) library to import our data to this workbook as a DataFrame."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.2. Data Dictionary \n",
"The [Understat](https://understat.com/) dataset has twenty features (columns) with the following definitions and data types:\n",
"\n",
"| Feature | Data type |\n",
"|------|-----|\n",
"| `id` | `int64`\n",
"| `minute` | `int64`\n",
"| `result` | `object`\n",
"| `X` | `float64`\n",
"| `Y` | `float64`\n",
"| `xG` | `float64`\n",
"| `player` | `object`\n",
"| `h_a` | `object`\n",
"| `player_id` | `int64`\n",
"| `situation` | `object`\n",
"| `season` | `int64`\n",
"| `shotType` | `object`\n",
"| `match_id` | `int64`\n",
"| `h_team` | `object`\n",
"| `a_team` | `object`\n",
"| `h_goals` | `int64`\n",
"| `a_goals` | `int64`\n",
"| `date` | `object`\n",
"| `player_assisted` | `object`\n",
"| `lastAction` | `object`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.3. Creating the DataFrame \n",
"The data has been scraped using the [Ben Torvaney](https://twitter.com/Torvaney)'s [Understat Scraper in R](https://gist.github.com/Torvaney/42cd82addb3ba2c4f33ec3247e66889c)\n",
"\n",
"This information collected for all the players is converted to a [pandas](http://pandas.pydata.org/) DataFrame from which we can view and manipulate the data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 14/15"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_1415_raw\n",
"\n",
"## Look for most recent CSV file\n",
"list_of_files_1415 = glob.glob(data_dir_understat + '/raw/1415/*') # * means all if need specific format then *.csv\n",
"filepath_latest_1415 = max(list_of_files_1415, key=os.path.getctime)\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_1415_raw = pd.read_csv(filepath_latest_1415)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 15/16"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_1516_raw\n",
"\n",
"## Look for most recent CSV file\n",
"list_of_files_1516 = glob.glob(data_dir_understat + '/raw/1516/*')\n",
"filepath_latest_1516 = max(list_of_files_1516, key=os.path.getctime)\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_1516_raw = pd.read_csv(filepath_latest_1516)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 16/17"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_1617_raw\n",
"\n",
"## Look for most recent CSV file\n",
"list_of_files_1617 = glob.glob(data_dir_understat + '/raw/1617/*')\n",
"filepath_latest_1617 = max(list_of_files_1617, key=os.path.getctime)\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_1617_raw = pd.read_csv(filepath_latest_1617)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 17/18"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_1718_raw\n",
"\n",
"## Look for most recent CSV file\n",
"list_of_files_1718 = glob.glob(data_dir_understat + '/raw/1718/*')\n",
"filepath_latest_1718 = max(list_of_files_1718, key=os.path.getctime)\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_1718_raw = pd.read_csv(filepath_latest_1718)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 18/19"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_1819_raw\n",
"\n",
"## Look for most recent CSV file\n",
"list_of_files_1819 = glob.glob(data_dir_understat + '/raw/1819/*')\n",
"filepath_latest_1819 = max(list_of_files_1819, key=os.path.getctime)\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_1819_raw = pd.read_csv(filepath_latest_1819)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 19/20"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_1920_raw\n",
"\n",
"## Look for most recent CSV file\n",
"list_of_files_1920 = glob.glob(data_dir_understat + '/raw/1920/*') # * means all if need specific format then *.csv\n",
"filepath_latest_1920 = max(list_of_files_1920, key=os.path.getctime)\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_1920_raw = pd.read_csv(filepath_latest_1920)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 20/21"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# Import data as a pandas DataFrame, df_understat_2021_raw\n",
"\n",
"## Look for most recent CSV file\n",
"filepath_2021 = data_dir_understat + '/raw/2021/big5_shots_2021_latest.csv'\n",
"\n",
"## Load in most recently parsed CSV file\n",
"df_understat_2021_raw = pd.read_csv(filepath_2021)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.4. Preliminary Data Handling \n",
"Let's quality of the dataset by looking first and last rows in pandas using the [head()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.head.html) and [tail()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.tail.html) methods."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 14/15"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 14511 \n",
" 12 \n",
" SavedShot \n",
" 0.728 \n",
" 0.501 \n",
" 0.018741 \n",
" Wayne Rooney \n",
" h \n",
" 629 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16T12:45:00Z \n",
" Darren Fletcher \n",
" Pass \n",
" \n",
" \n",
" 1 \n",
" 14512 \n",
" 16 \n",
" BlockedShot \n",
" 0.789 \n",
" 0.336 \n",
" 0.015598 \n",
" Wayne Rooney \n",
" h \n",
" 629 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16T12:45:00Z \n",
" Chicharito \n",
" TakeOn \n",
" \n",
" \n",
" 2 \n",
" 14513 \n",
" 25 \n",
" SavedShot \n",
" 0.914 \n",
" 0.188 \n",
" 0.064923 \n",
" Juan Mata \n",
" h \n",
" 554 \n",
" DirectFreekick \n",
" 2014 \n",
" LeftFoot \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16T12:45:00Z \n",
" NaN \n",
" Standard \n",
" \n",
" \n",
" 3 \n",
" 14514 \n",
" 26 \n",
" SavedShot \n",
" 0.920 \n",
" 0.482 \n",
" 0.057788 \n",
" Wayne Rooney \n",
" h \n",
" 629 \n",
" OpenPlay \n",
" 2014 \n",
" Head \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16T12:45:00Z \n",
" Ashley Young \n",
" Aerial \n",
" \n",
" \n",
" 4 \n",
" 14516 \n",
" 33 \n",
" MissedShots \n",
" 0.922 \n",
" 0.590 \n",
" 0.048801 \n",
" Wayne Rooney \n",
" h \n",
" 629 \n",
" FromCorner \n",
" 2014 \n",
" Head \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16T12:45:00Z \n",
" Juan Mata \n",
" Cross \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player h_a \\\n",
"0 14511 12 SavedShot 0.728 0.501 0.018741 Wayne Rooney h \n",
"1 14512 16 BlockedShot 0.789 0.336 0.015598 Wayne Rooney h \n",
"2 14513 25 SavedShot 0.914 0.188 0.064923 Juan Mata h \n",
"3 14514 26 SavedShot 0.920 0.482 0.057788 Wayne Rooney h \n",
"4 14516 33 MissedShots 0.922 0.590 0.048801 Wayne Rooney h \n",
"\n",
" player_id situation season shotType match_id h_team \\\n",
"0 629 OpenPlay 2014 RightFoot 4749 Manchester United \n",
"1 629 OpenPlay 2014 RightFoot 4749 Manchester United \n",
"2 554 DirectFreekick 2014 LeftFoot 4749 Manchester United \n",
"3 629 OpenPlay 2014 Head 4749 Manchester United \n",
"4 629 FromCorner 2014 Head 4749 Manchester United \n",
"\n",
" a_team h_goals a_goals date player_assisted lastAction \n",
"0 Swansea 1 2 2014-08-16T12:45:00Z Darren Fletcher Pass \n",
"1 Swansea 1 2 2014-08-16T12:45:00Z Chicharito TakeOn \n",
"2 Swansea 1 2 2014-08-16T12:45:00Z NaN Standard \n",
"3 Swansea 1 2 2014-08-16T12:45:00Z Ashley Young Aerial \n",
"4 Swansea 1 2 2014-08-16T12:45:00Z Juan Mata Cross "
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_1415_raw\n",
"df_understat_1415_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 45743 \n",
" 7438 \n",
" 64 \n",
" MissedShots \n",
" 0.693 \n",
" 0.521 \n",
" 0.012393 \n",
" Corentin Tolisso \n",
" a \n",
" 3603 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 5884 \n",
" Rennes \n",
" Lyon \n",
" 0 \n",
" 1 \n",
" 2015-05-23T20:00:00Z \n",
" Clinton N'Jie \n",
" Pass \n",
" \n",
" \n",
" 45744 \n",
" 7440 \n",
" 68 \n",
" MissedShots \n",
" 0.852 \n",
" 0.233 \n",
" 0.021710 \n",
" Clinton N'Jie \n",
" a \n",
" 960 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 5884 \n",
" Rennes \n",
" Lyon \n",
" 0 \n",
" 1 \n",
" 2015-05-23T20:00:00Z \n",
" Corentin Tolisso \n",
" Chipped \n",
" \n",
" \n",
" 45745 \n",
" 7442 \n",
" 77 \n",
" MissedShots \n",
" 0.713 \n",
" 0.572 \n",
" 0.013678 \n",
" Maxime Gonalons \n",
" a \n",
" 3274 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 5884 \n",
" Rennes \n",
" Lyon \n",
" 0 \n",
" 1 \n",
" 2015-05-23T20:00:00Z \n",
" Gueida Fofana \n",
" Pass \n",
" \n",
" \n",
" 45746 \n",
" 7443 \n",
" 85 \n",
" SavedShot \n",
" 0.761 \n",
" 0.649 \n",
" 0.020611 \n",
" Yassine Benzia \n",
" a \n",
" 3366 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 5884 \n",
" Rennes \n",
" Lyon \n",
" 0 \n",
" 1 \n",
" 2015-05-23T20:00:00Z \n",
" Gueida Fofana \n",
" Pass \n",
" \n",
" \n",
" 45747 \n",
" 7444 \n",
" 85 \n",
" Goal \n",
" 0.917 \n",
" 0.452 \n",
" 0.594141 \n",
" Clinton N'Jie \n",
" a \n",
" 960 \n",
" OpenPlay \n",
" 2014 \n",
" RightFoot \n",
" 5884 \n",
" Rennes \n",
" Lyon \n",
" 0 \n",
" 1 \n",
" 2015-05-23T20:00:00Z \n",
" Maxime Gonalons \n",
" TakeOn \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"45743 7438 64 MissedShots 0.693 0.521 0.012393 Corentin Tolisso \n",
"45744 7440 68 MissedShots 0.852 0.233 0.021710 Clinton N'Jie \n",
"45745 7442 77 MissedShots 0.713 0.572 0.013678 Maxime Gonalons \n",
"45746 7443 85 SavedShot 0.761 0.649 0.020611 Yassine Benzia \n",
"45747 7444 85 Goal 0.917 0.452 0.594141 Clinton N'Jie \n",
"\n",
" h_a player_id situation season shotType match_id h_team a_team \\\n",
"45743 a 3603 OpenPlay 2014 RightFoot 5884 Rennes Lyon \n",
"45744 a 960 OpenPlay 2014 RightFoot 5884 Rennes Lyon \n",
"45745 a 3274 OpenPlay 2014 RightFoot 5884 Rennes Lyon \n",
"45746 a 3366 OpenPlay 2014 RightFoot 5884 Rennes Lyon \n",
"45747 a 960 OpenPlay 2014 RightFoot 5884 Rennes Lyon \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"45743 0 1 2015-05-23T20:00:00Z Clinton N'Jie Pass \n",
"45744 0 1 2015-05-23T20:00:00Z Corentin Tolisso Chipped \n",
"45745 0 1 2015-05-23T20:00:00Z Gueida Fofana Pass \n",
"45746 0 1 2015-05-23T20:00:00Z Gueida Fofana Pass \n",
"45747 0 1 2015-05-23T20:00:00Z Maxime Gonalons TakeOn "
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, ddf_understat_1415_raw\n",
"df_understat_1415_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 15/16"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 200247 \n",
" 27 \n",
" BlockedShot \n",
" 0.794 \n",
" 0.421 \n",
" 0.104347 \n",
" Juan Mata \n",
" h \n",
" 554 \n",
" DirectFreekick \n",
" 2015 \n",
" LeftFoot \n",
" 81 \n",
" Manchester United \n",
" Tottenham \n",
" 1 \n",
" 0 \n",
" 2015-08-08T15:45:00Z \n",
" NaN \n",
" Standard \n",
" \n",
" \n",
" 1 \n",
" 200248 \n",
" 27 \n",
" BlockedShot \n",
" 0.860 \n",
" 0.627 \n",
" 0.064342 \n",
" Memphis Depay \n",
" h \n",
" 555 \n",
" SetPiece \n",
" 2015 \n",
" RightFoot \n",
" 81 \n",
" Manchester United \n",
" Tottenham \n",
" 1 \n",
" 0 \n",
" 2015-08-08T15:45:00Z \n",
" Ashley Young \n",
" Pass \n",
" \n",
" \n",
" 2 \n",
" 200249 \n",
" 35 \n",
" BlockedShot \n",
" 0.843 \n",
" 0.333 \n",
" 0.057157 \n",
" Juan Mata \n",
" h \n",
" 554 \n",
" OpenPlay \n",
" 2015 \n",
" LeftFoot \n",
" 81 \n",
" Manchester United \n",
" Tottenham \n",
" 1 \n",
" 0 \n",
" 2015-08-08T15:45:00Z \n",
" Wayne Rooney \n",
" Pass \n",
" \n",
" \n",
" 3 \n",
" 200250 \n",
" 35 \n",
" MissedShots \n",
" 0.848 \n",
" 0.533 \n",
" 0.092141 \n",
" Juan Mata \n",
" h \n",
" 554 \n",
" OpenPlay \n",
" 2015 \n",
" LeftFoot \n",
" 81 \n",
" Manchester United \n",
" Tottenham \n",
" 1 \n",
" 0 \n",
" 2015-08-08T15:45:00Z \n",
" NaN \n",
" Tackle \n",
" \n",
" \n",
" 4 \n",
" 200251 \n",
" 40 \n",
" BlockedShot \n",
" 0.812 \n",
" 0.707 \n",
" 0.035742 \n",
" Memphis Depay \n",
" h \n",
" 555 \n",
" OpenPlay \n",
" 2015 \n",
" RightFoot \n",
" 81 \n",
" Manchester United \n",
" Tottenham \n",
" 1 \n",
" 0 \n",
" 2015-08-08T15:45:00Z \n",
" Michael Carrick \n",
" BallRecovery \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player h_a \\\n",
"0 200247 27 BlockedShot 0.794 0.421 0.104347 Juan Mata h \n",
"1 200248 27 BlockedShot 0.860 0.627 0.064342 Memphis Depay h \n",
"2 200249 35 BlockedShot 0.843 0.333 0.057157 Juan Mata h \n",
"3 200250 35 MissedShots 0.848 0.533 0.092141 Juan Mata h \n",
"4 200251 40 BlockedShot 0.812 0.707 0.035742 Memphis Depay h \n",
"\n",
" player_id situation season shotType match_id h_team \\\n",
"0 554 DirectFreekick 2015 LeftFoot 81 Manchester United \n",
"1 555 SetPiece 2015 RightFoot 81 Manchester United \n",
"2 554 OpenPlay 2015 LeftFoot 81 Manchester United \n",
"3 554 OpenPlay 2015 LeftFoot 81 Manchester United \n",
"4 555 OpenPlay 2015 RightFoot 81 Manchester United \n",
"\n",
" a_team h_goals a_goals date player_assisted \\\n",
"0 Tottenham 1 0 2015-08-08T15:45:00Z NaN \n",
"1 Tottenham 1 0 2015-08-08T15:45:00Z Ashley Young \n",
"2 Tottenham 1 0 2015-08-08T15:45:00Z Wayne Rooney \n",
"3 Tottenham 1 0 2015-08-08T15:45:00Z NaN \n",
"4 Tottenham 1 0 2015-08-08T15:45:00Z Michael Carrick \n",
"\n",
" lastAction \n",
"0 Standard \n",
"1 Pass \n",
"2 Pass \n",
"3 Tackle \n",
"4 BallRecovery "
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_1516_raw\n",
"df_understat_1516_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 45468 \n",
" 68494 \n",
" 60 \n",
" MissedShots \n",
" 0.795 \n",
" 0.723 \n",
" 0.023267 \n",
" François Moubandje \n",
" a \n",
" 3205 \n",
" OpenPlay \n",
" 2015 \n",
" RightFoot \n",
" 2248 \n",
" Angers \n",
" Toulouse \n",
" 2 \n",
" 3 \n",
" 2016-05-14T23:00:00Z \n",
" Marcel Tisserand \n",
" Pass \n",
" \n",
" \n",
" 45469 \n",
" 68496 \n",
" 64 \n",
" MissedShots \n",
" 0.883 \n",
" 0.347 \n",
" 0.046925 \n",
" Óscar Trejo \n",
" a \n",
" 3208 \n",
" SetPiece \n",
" 2015 \n",
" LeftFoot \n",
" 2248 \n",
" Angers \n",
" Toulouse \n",
" 2 \n",
" 3 \n",
" 2016-05-14T23:00:00Z \n",
" Adrien Regattin \n",
" Pass \n",
" \n",
" \n",
" 45470 \n",
" 68497 \n",
" 74 \n",
" SavedShot \n",
" 0.902 \n",
" 0.313 \n",
" 0.055296 \n",
" Wissam Ben Yedder \n",
" a \n",
" 3210 \n",
" OpenPlay \n",
" 2015 \n",
" RightFoot \n",
" 2248 \n",
" Angers \n",
" Toulouse \n",
" 2 \n",
" 3 \n",
" 2016-05-14T23:00:00Z \n",
" Jean-Armel Kana-Biyik \n",
" HeadPass \n",
" \n",
" \n",
" 45471 \n",
" 68499 \n",
" 77 \n",
" Goal \n",
" 0.932 \n",
" 0.478 \n",
" 0.109640 \n",
" Martin Braithwaite \n",
" a \n",
" 3211 \n",
" OpenPlay \n",
" 2015 \n",
" RightFoot \n",
" 2248 \n",
" Angers \n",
" Toulouse \n",
" 2 \n",
" 3 \n",
" 2016-05-14T23:00:00Z \n",
" Pavle Ninkov \n",
" Cross \n",
" \n",
" \n",
" 45472 \n",
" 68500 \n",
" 79 \n",
" Goal \n",
" 0.874 \n",
" 0.197 \n",
" 0.063145 \n",
" Yann Bodiger \n",
" a \n",
" 3206 \n",
" DirectFreekick \n",
" 2015 \n",
" LeftFoot \n",
" 2248 \n",
" Angers \n",
" Toulouse \n",
" 2 \n",
" 3 \n",
" 2016-05-14T23:00:00Z \n",
" NaN \n",
" Standard \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"45468 68494 60 MissedShots 0.795 0.723 0.023267 François Moubandje \n",
"45469 68496 64 MissedShots 0.883 0.347 0.046925 Óscar Trejo \n",
"45470 68497 74 SavedShot 0.902 0.313 0.055296 Wissam Ben Yedder \n",
"45471 68499 77 Goal 0.932 0.478 0.109640 Martin Braithwaite \n",
"45472 68500 79 Goal 0.874 0.197 0.063145 Yann Bodiger \n",
"\n",
" h_a player_id situation season shotType match_id h_team \\\n",
"45468 a 3205 OpenPlay 2015 RightFoot 2248 Angers \n",
"45469 a 3208 SetPiece 2015 LeftFoot 2248 Angers \n",
"45470 a 3210 OpenPlay 2015 RightFoot 2248 Angers \n",
"45471 a 3211 OpenPlay 2015 RightFoot 2248 Angers \n",
"45472 a 3206 DirectFreekick 2015 LeftFoot 2248 Angers \n",
"\n",
" a_team h_goals a_goals date \\\n",
"45468 Toulouse 2 3 2016-05-14T23:00:00Z \n",
"45469 Toulouse 2 3 2016-05-14T23:00:00Z \n",
"45470 Toulouse 2 3 2016-05-14T23:00:00Z \n",
"45471 Toulouse 2 3 2016-05-14T23:00:00Z \n",
"45472 Toulouse 2 3 2016-05-14T23:00:00Z \n",
"\n",
" player_assisted lastAction \n",
"45468 Marcel Tisserand Pass \n",
"45469 Adrien Regattin Pass \n",
"45470 Jean-Armel Kana-Biyik HeadPass \n",
"45471 Pavle Ninkov Cross \n",
"45472 NaN Standard "
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, df_understat_1516_raw\n",
"df_understat_1516_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 16/17"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 112236 \n",
" 5 \n",
" MissedShots \n",
" 0.916 \n",
" 0.585 \n",
" 0.016872 \n",
" Curtis Davies \n",
" h \n",
" 1686 \n",
" FromCorner \n",
" 2016 \n",
" Head \n",
" 461 \n",
" Hull \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2016-08-13T15:30:00Z \n",
" Robert Snodgrass \n",
" Aerial \n",
" \n",
" \n",
" 1 \n",
" 112242 \n",
" 29 \n",
" MissedShots \n",
" 0.758 \n",
" 0.188 \n",
" 0.031149 \n",
" Robert Snodgrass \n",
" h \n",
" 1691 \n",
" DirectFreekick \n",
" 2016 \n",
" LeftFoot \n",
" 461 \n",
" Hull \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2016-08-13T15:30:00Z \n",
" NaN \n",
" Standard \n",
" \n",
" \n",
" 2 \n",
" 112243 \n",
" 33 \n",
" MissedShots \n",
" 0.839 \n",
" 0.324 \n",
" 0.039379 \n",
" Abel Hernández \n",
" h \n",
" 1698 \n",
" OpenPlay \n",
" 2016 \n",
" LeftFoot \n",
" 461 \n",
" Hull \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2016-08-13T15:30:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
" 3 \n",
" 112247 \n",
" 41 \n",
" MissedShots \n",
" 0.748 \n",
" 0.324 \n",
" 0.015570 \n",
" Robert Snodgrass \n",
" h \n",
" 1691 \n",
" OpenPlay \n",
" 2016 \n",
" LeftFoot \n",
" 461 \n",
" Hull \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2016-08-13T15:30:00Z \n",
" Adama Diomande \n",
" Pass \n",
" \n",
" \n",
" 4 \n",
" 112249 \n",
" 45 \n",
" SavedShot \n",
" 0.923 \n",
" 0.606 \n",
" 0.033541 \n",
" Curtis Davies \n",
" h \n",
" 1686 \n",
" FromCorner \n",
" 2016 \n",
" Head \n",
" 461 \n",
" Hull \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2016-08-13T15:30:00Z \n",
" Robert Snodgrass \n",
" Cross \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player h_a \\\n",
"0 112236 5 MissedShots 0.916 0.585 0.016872 Curtis Davies h \n",
"1 112242 29 MissedShots 0.758 0.188 0.031149 Robert Snodgrass h \n",
"2 112243 33 MissedShots 0.839 0.324 0.039379 Abel Hernández h \n",
"3 112247 41 MissedShots 0.748 0.324 0.015570 Robert Snodgrass h \n",
"4 112249 45 SavedShot 0.923 0.606 0.033541 Curtis Davies h \n",
"\n",
" player_id situation season shotType match_id h_team a_team \\\n",
"0 1686 FromCorner 2016 Head 461 Hull Leicester \n",
"1 1691 DirectFreekick 2016 LeftFoot 461 Hull Leicester \n",
"2 1698 OpenPlay 2016 LeftFoot 461 Hull Leicester \n",
"3 1691 OpenPlay 2016 LeftFoot 461 Hull Leicester \n",
"4 1686 FromCorner 2016 Head 461 Hull Leicester \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"0 2 1 2016-08-13T15:30:00Z Robert Snodgrass Aerial \n",
"1 2 1 2016-08-13T15:30:00Z NaN Standard \n",
"2 2 1 2016-08-13T15:30:00Z NaN None \n",
"3 2 1 2016-08-13T15:30:00Z Adama Diomande Pass \n",
"4 2 1 2016-08-13T15:30:00Z Robert Snodgrass Cross "
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_1617_raw\n",
"df_understat_1617_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 45873 \n",
" 110628 \n",
" 70 \n",
" MissedShots \n",
" 0.894 \n",
" 0.605 \n",
" 0.031307 \n",
" Mevlüt Erdinc \n",
" a \n",
" 104 \n",
" OpenPlay \n",
" 2016 \n",
" Head \n",
" 4294 \n",
" Guingamp \n",
" Metz \n",
" 1 \n",
" 0 \n",
" 2017-05-20T20:00:00Z \n",
" Matthieu Udol \n",
" Cross \n",
" \n",
" \n",
" 45874 \n",
" 110630 \n",
" 75 \n",
" BlockedShot \n",
" 0.872 \n",
" 0.479 \n",
" 0.098524 \n",
" Mevlüt Erdinc \n",
" a \n",
" 104 \n",
" OpenPlay \n",
" 2016 \n",
" LeftFoot \n",
" 4294 \n",
" Guingamp \n",
" Metz \n",
" 1 \n",
" 0 \n",
" 2017-05-20T20:00:00Z \n",
" Opa Nguette \n",
" Pass \n",
" \n",
" \n",
" 45875 \n",
" 110632 \n",
" 79 \n",
" MissedShots \n",
" 0.901 \n",
" 0.135 \n",
" 0.018259 \n",
" Mevlüt Erdinc \n",
" a \n",
" 104 \n",
" OpenPlay \n",
" 2016 \n",
" RightFoot \n",
" 4294 \n",
" Guingamp \n",
" Metz \n",
" 1 \n",
" 0 \n",
" 2017-05-20T20:00:00Z \n",
" Renaud Cohade \n",
" Pass \n",
" \n",
" \n",
" 45876 \n",
" 110634 \n",
" 85 \n",
" MissedShots \n",
" 0.983 \n",
" 0.569 \n",
" 0.088932 \n",
" Cheick Doukoure \n",
" a \n",
" 4741 \n",
" SetPiece \n",
" 2016 \n",
" RightFoot \n",
" 4294 \n",
" Guingamp \n",
" Metz \n",
" 1 \n",
" 0 \n",
" 2017-05-20T20:00:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
" 45877 \n",
" 110635 \n",
" 88 \n",
" MissedShots \n",
" 0.721 \n",
" 0.578 \n",
" 0.012905 \n",
" Florent Mollet \n",
" a \n",
" 5677 \n",
" OpenPlay \n",
" 2016 \n",
" RightFoot \n",
" 4294 \n",
" Guingamp \n",
" Metz \n",
" 1 \n",
" 0 \n",
" 2017-05-20T20:00:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"45873 110628 70 MissedShots 0.894 0.605 0.031307 Mevlüt Erdinc \n",
"45874 110630 75 BlockedShot 0.872 0.479 0.098524 Mevlüt Erdinc \n",
"45875 110632 79 MissedShots 0.901 0.135 0.018259 Mevlüt Erdinc \n",
"45876 110634 85 MissedShots 0.983 0.569 0.088932 Cheick Doukoure \n",
"45877 110635 88 MissedShots 0.721 0.578 0.012905 Florent Mollet \n",
"\n",
" h_a player_id situation season shotType match_id h_team a_team \\\n",
"45873 a 104 OpenPlay 2016 Head 4294 Guingamp Metz \n",
"45874 a 104 OpenPlay 2016 LeftFoot 4294 Guingamp Metz \n",
"45875 a 104 OpenPlay 2016 RightFoot 4294 Guingamp Metz \n",
"45876 a 4741 SetPiece 2016 RightFoot 4294 Guingamp Metz \n",
"45877 a 5677 OpenPlay 2016 RightFoot 4294 Guingamp Metz \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"45873 1 0 2017-05-20T20:00:00Z Matthieu Udol Cross \n",
"45874 1 0 2017-05-20T20:00:00Z Opa Nguette Pass \n",
"45875 1 0 2017-05-20T20:00:00Z Renaud Cohade Pass \n",
"45876 1 0 2017-05-20T20:00:00Z NaN None \n",
"45877 1 0 2017-05-20T20:00:00Z NaN None "
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, df_understat_1617_raw\n",
"df_understat_1617_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 17/18"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 158133 \n",
" 1 \n",
" Goal \n",
" 0.885 \n",
" 0.526 \n",
" 0.043622 \n",
" Alexandre Lacazette \n",
" h \n",
" 3277 \n",
" OpenPlay \n",
" 2017 \n",
" Head \n",
" 7119 \n",
" Arsenal \n",
" Leicester \n",
" 4 \n",
" 3 \n",
" 2017-08-11T19:45:00Z \n",
" Mohamed Elneny \n",
" Chipped \n",
" \n",
" \n",
" 1 \n",
" 158136 \n",
" 7 \n",
" MissedShots \n",
" 0.807 \n",
" 0.720 \n",
" 0.017942 \n",
" Alex Oxlade-Chamberlain \n",
" h \n",
" 966 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 7119 \n",
" Arsenal \n",
" Leicester \n",
" 4 \n",
" 3 \n",
" 2017-08-11T19:45:00Z \n",
" Mesut Özil \n",
" TakeOn \n",
" \n",
" \n",
" 2 \n",
" 158137 \n",
" 13 \n",
" SavedShot \n",
" 0.786 \n",
" 0.643 \n",
" 0.028923 \n",
" Alex Oxlade-Chamberlain \n",
" h \n",
" 966 \n",
" OpenPlay \n",
" 2017 \n",
" RightFoot \n",
" 7119 \n",
" Arsenal \n",
" Leicester \n",
" 4 \n",
" 3 \n",
" 2017-08-11T19:45:00Z \n",
" Mesut Özil \n",
" Dispossessed \n",
" \n",
" \n",
" 3 \n",
" 158138 \n",
" 21 \n",
" BlockedShot \n",
" 0.906 \n",
" 0.605 \n",
" 0.375224 \n",
" Danny Welbeck \n",
" h \n",
" 501 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 7119 \n",
" Arsenal \n",
" Leicester \n",
" 4 \n",
" 3 \n",
" 2017-08-11T19:45:00Z \n",
" Mesut Özil \n",
" Pass \n",
" \n",
" \n",
" 4 \n",
" 158139 \n",
" 21 \n",
" MissedShots \n",
" 0.676 \n",
" 0.573 \n",
" 0.010858 \n",
" Granit Xhaka \n",
" h \n",
" 204 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 7119 \n",
" Arsenal \n",
" Leicester \n",
" 4 \n",
" 3 \n",
" 2017-08-11T19:45:00Z \n",
" Mohamed Elneny \n",
" Pass \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG \\\n",
"0 158133 1 Goal 0.885 0.526 0.043622 \n",
"1 158136 7 MissedShots 0.807 0.720 0.017942 \n",
"2 158137 13 SavedShot 0.786 0.643 0.028923 \n",
"3 158138 21 BlockedShot 0.906 0.605 0.375224 \n",
"4 158139 21 MissedShots 0.676 0.573 0.010858 \n",
"\n",
" player h_a player_id situation season shotType \\\n",
"0 Alexandre Lacazette h 3277 OpenPlay 2017 Head \n",
"1 Alex Oxlade-Chamberlain h 966 OpenPlay 2017 LeftFoot \n",
"2 Alex Oxlade-Chamberlain h 966 OpenPlay 2017 RightFoot \n",
"3 Danny Welbeck h 501 OpenPlay 2017 LeftFoot \n",
"4 Granit Xhaka h 204 OpenPlay 2017 LeftFoot \n",
"\n",
" match_id h_team a_team h_goals a_goals date \\\n",
"0 7119 Arsenal Leicester 4 3 2017-08-11T19:45:00Z \n",
"1 7119 Arsenal Leicester 4 3 2017-08-11T19:45:00Z \n",
"2 7119 Arsenal Leicester 4 3 2017-08-11T19:45:00Z \n",
"3 7119 Arsenal Leicester 4 3 2017-08-11T19:45:00Z \n",
"4 7119 Arsenal Leicester 4 3 2017-08-11T19:45:00Z \n",
"\n",
" player_assisted lastAction \n",
"0 Mohamed Elneny Chipped \n",
"1 Mesut Özil TakeOn \n",
"2 Mesut Özil Dispossessed \n",
"3 Mesut Özil Pass \n",
"4 Mohamed Elneny Pass "
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_1718_raw\n",
"df_understat_1718_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 45373 \n",
" 216203 \n",
" 48 \n",
" BlockedShot \n",
" 0.973 \n",
" 0.699 \n",
" 0.070225 \n",
" Francois Kamano \n",
" a \n",
" 3333 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 8944 \n",
" Metz \n",
" Bordeaux \n",
" 0 \n",
" 4 \n",
" 2018-05-19T19:00:00Z \n",
" NaN \n",
" BallRecovery \n",
" \n",
" \n",
" 45374 \n",
" 216204 \n",
" 52 \n",
" BlockedShot \n",
" 0.745 \n",
" 0.286 \n",
" 0.041425 \n",
" Malcom \n",
" a \n",
" 3262 \n",
" DirectFreekick \n",
" 2017 \n",
" LeftFoot \n",
" 8944 \n",
" Metz \n",
" Bordeaux \n",
" 0 \n",
" 4 \n",
" 2018-05-19T19:00:00Z \n",
" NaN \n",
" Standard \n",
" \n",
" \n",
" 45375 \n",
" 216205 \n",
" 59 \n",
" BlockedShot \n",
" 0.867 \n",
" 0.404 \n",
" 0.120161 \n",
" Younousse Sankhare \n",
" a \n",
" 3474 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 8944 \n",
" Metz \n",
" Bordeaux \n",
" 0 \n",
" 4 \n",
" 2018-05-19T19:00:00Z \n",
" Youssouf Sabaly \n",
" Pass \n",
" \n",
" \n",
" 45376 \n",
" 216210 \n",
" 76 \n",
" Goal \n",
" 0.870 \n",
" 0.857 \n",
" 0.028518 \n",
" Nicolas de Preville \n",
" a \n",
" 3244 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 8944 \n",
" Metz \n",
" Bordeaux \n",
" 0 \n",
" 4 \n",
" 2018-05-19T19:00:00Z \n",
" Maxime Poundje \n",
" Pass \n",
" \n",
" \n",
" 45377 \n",
" 216211 \n",
" 84 \n",
" MissedShots \n",
" 0.733 \n",
" 0.451 \n",
" 0.040653 \n",
" Soualiho Meité \n",
" a \n",
" 3739 \n",
" OpenPlay \n",
" 2017 \n",
" LeftFoot \n",
" 8944 \n",
" Metz \n",
" Bordeaux \n",
" 0 \n",
" 4 \n",
" 2018-05-19T19:00:00Z \n",
" Jaroslav Plasil \n",
" TakeOn \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG \\\n",
"45373 216203 48 BlockedShot 0.973 0.699 0.070225 \n",
"45374 216204 52 BlockedShot 0.745 0.286 0.041425 \n",
"45375 216205 59 BlockedShot 0.867 0.404 0.120161 \n",
"45376 216210 76 Goal 0.870 0.857 0.028518 \n",
"45377 216211 84 MissedShots 0.733 0.451 0.040653 \n",
"\n",
" player h_a player_id situation season shotType \\\n",
"45373 Francois Kamano a 3333 OpenPlay 2017 LeftFoot \n",
"45374 Malcom a 3262 DirectFreekick 2017 LeftFoot \n",
"45375 Younousse Sankhare a 3474 OpenPlay 2017 LeftFoot \n",
"45376 Nicolas de Preville a 3244 OpenPlay 2017 LeftFoot \n",
"45377 Soualiho Meité a 3739 OpenPlay 2017 LeftFoot \n",
"\n",
" match_id h_team a_team h_goals a_goals date \\\n",
"45373 8944 Metz Bordeaux 0 4 2018-05-19T19:00:00Z \n",
"45374 8944 Metz Bordeaux 0 4 2018-05-19T19:00:00Z \n",
"45375 8944 Metz Bordeaux 0 4 2018-05-19T19:00:00Z \n",
"45376 8944 Metz Bordeaux 0 4 2018-05-19T19:00:00Z \n",
"45377 8944 Metz Bordeaux 0 4 2018-05-19T19:00:00Z \n",
"\n",
" player_assisted lastAction \n",
"45373 NaN BallRecovery \n",
"45374 NaN Standard \n",
"45375 Youssouf Sabaly Pass \n",
"45376 Maxime Poundje Pass \n",
"45377 Jaroslav Plasil TakeOn "
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, df_understat_1718_raw\n",
"df_understat_1718_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 18/19"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 232811 \n",
" 1 \n",
" BlockedShot \n",
" 0.863 \n",
" 0.711 \n",
" 0.039962 \n",
" Alexis Sánchez \n",
" h \n",
" 498 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 9197 \n",
" Manchester United \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2018-08-10T22:00:00Z \n",
" Luke Shaw \n",
" Pass \n",
" \n",
" \n",
" 1 \n",
" 232812 \n",
" 2 \n",
" Goal \n",
" 0.885 \n",
" 0.500 \n",
" 0.761169 \n",
" Paul Pogba \n",
" h \n",
" 1740 \n",
" Penalty \n",
" 2018 \n",
" RightFoot \n",
" 9197 \n",
" Manchester United \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2018-08-10T22:00:00Z \n",
" NaN \n",
" Standard \n",
" \n",
" \n",
" 2 \n",
" 232818 \n",
" 39 \n",
" SavedShot \n",
" 0.724 \n",
" 0.655 \n",
" 0.018396 \n",
" Paul Pogba \n",
" h \n",
" 1740 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 9197 \n",
" Manchester United \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2018-08-10T22:00:00Z \n",
" Alexis Sánchez \n",
" Pass \n",
" \n",
" \n",
" 3 \n",
" 232819 \n",
" 40 \n",
" SavedShot \n",
" 0.880 \n",
" 0.653 \n",
" 0.081215 \n",
" Luke Shaw \n",
" h \n",
" 1006 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 9197 \n",
" Manchester United \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2018-08-10T22:00:00Z \n",
" Juan Mata \n",
" Chipped \n",
" \n",
" \n",
" 4 \n",
" 232821 \n",
" 55 \n",
" SavedShot \n",
" 0.781 \n",
" 0.330 \n",
" 0.028309 \n",
" Matteo Darmian \n",
" h \n",
" 557 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 9197 \n",
" Manchester United \n",
" Leicester \n",
" 2 \n",
" 1 \n",
" 2018-08-10T22:00:00Z \n",
" Alexis Sánchez \n",
" Pass \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player h_a \\\n",
"0 232811 1 BlockedShot 0.863 0.711 0.039962 Alexis Sánchez h \n",
"1 232812 2 Goal 0.885 0.500 0.761169 Paul Pogba h \n",
"2 232818 39 SavedShot 0.724 0.655 0.018396 Paul Pogba h \n",
"3 232819 40 SavedShot 0.880 0.653 0.081215 Luke Shaw h \n",
"4 232821 55 SavedShot 0.781 0.330 0.028309 Matteo Darmian h \n",
"\n",
" player_id situation season shotType match_id h_team \\\n",
"0 498 OpenPlay 2018 RightFoot 9197 Manchester United \n",
"1 1740 Penalty 2018 RightFoot 9197 Manchester United \n",
"2 1740 OpenPlay 2018 RightFoot 9197 Manchester United \n",
"3 1006 OpenPlay 2018 RightFoot 9197 Manchester United \n",
"4 557 OpenPlay 2018 RightFoot 9197 Manchester United \n",
"\n",
" a_team h_goals a_goals date player_assisted \\\n",
"0 Leicester 2 1 2018-08-10T22:00:00Z Luke Shaw \n",
"1 Leicester 2 1 2018-08-10T22:00:00Z NaN \n",
"2 Leicester 2 1 2018-08-10T22:00:00Z Alexis Sánchez \n",
"3 Leicester 2 1 2018-08-10T22:00:00Z Juan Mata \n",
"4 Leicester 2 1 2018-08-10T22:00:00Z Alexis Sánchez \n",
"\n",
" lastAction \n",
"0 Pass \n",
"1 Standard \n",
"2 Pass \n",
"3 Chipped \n",
"4 Pass "
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_1819_raw\n",
"df_understat_1819_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 47196 \n",
" 303671 \n",
" 66 \n",
" MissedShots \n",
" 0.897 \n",
" 0.533 \n",
" 0.330207 \n",
" Jonathan Bamba \n",
" a \n",
" 3749 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 11022 \n",
" Rennes \n",
" Lille \n",
" 3 \n",
" 1 \n",
" 2019-05-24T19:05:00Z \n",
" Reinildo \n",
" Cross \n",
" \n",
" \n",
" 47197 \n",
" 303672 \n",
" 67 \n",
" SavedShot \n",
" 0.925 \n",
" 0.699 \n",
" 0.051046 \n",
" Jonathan Bamba \n",
" a \n",
" 3749 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 11022 \n",
" Rennes \n",
" Lille \n",
" 3 \n",
" 1 \n",
" 2019-05-24T19:05:00Z \n",
" Loïc Remy \n",
" Pass \n",
" \n",
" \n",
" 47198 \n",
" 303674 \n",
" 75 \n",
" MissedShots \n",
" 0.731 \n",
" 0.463 \n",
" 0.014794 \n",
" Nicolas Pepe \n",
" a \n",
" 5656 \n",
" OpenPlay \n",
" 2018 \n",
" LeftFoot \n",
" 11022 \n",
" Rennes \n",
" Lille \n",
" 3 \n",
" 1 \n",
" 2019-05-24T19:05:00Z \n",
" Thiago Mendes \n",
" Pass \n",
" \n",
" \n",
" 47199 \n",
" 303677 \n",
" 92 \n",
" BlockedShot \n",
" 0.896 \n",
" 0.640 \n",
" 0.074316 \n",
" Jonathan Bamba \n",
" a \n",
" 3749 \n",
" OpenPlay \n",
" 2018 \n",
" RightFoot \n",
" 11022 \n",
" Rennes \n",
" Lille \n",
" 3 \n",
" 1 \n",
" 2019-05-24T19:05:00Z \n",
" Jonathan Ikone \n",
" Pass \n",
" \n",
" \n",
" 47200 \n",
" 303678 \n",
" 92 \n",
" SavedShot \n",
" 0.919 \n",
" 0.509 \n",
" 0.103722 \n",
" Gabriel \n",
" a \n",
" 5613 \n",
" FromCorner \n",
" 2018 \n",
" Head \n",
" 11022 \n",
" Rennes \n",
" Lille \n",
" 3 \n",
" 1 \n",
" 2019-05-24T19:05:00Z \n",
" Nicolas Pepe \n",
" Cross \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"47196 303671 66 MissedShots 0.897 0.533 0.330207 Jonathan Bamba \n",
"47197 303672 67 SavedShot 0.925 0.699 0.051046 Jonathan Bamba \n",
"47198 303674 75 MissedShots 0.731 0.463 0.014794 Nicolas Pepe \n",
"47199 303677 92 BlockedShot 0.896 0.640 0.074316 Jonathan Bamba \n",
"47200 303678 92 SavedShot 0.919 0.509 0.103722 Gabriel \n",
"\n",
" h_a player_id situation season shotType match_id h_team a_team \\\n",
"47196 a 3749 OpenPlay 2018 RightFoot 11022 Rennes Lille \n",
"47197 a 3749 OpenPlay 2018 RightFoot 11022 Rennes Lille \n",
"47198 a 5656 OpenPlay 2018 LeftFoot 11022 Rennes Lille \n",
"47199 a 3749 OpenPlay 2018 RightFoot 11022 Rennes Lille \n",
"47200 a 5613 FromCorner 2018 Head 11022 Rennes Lille \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"47196 3 1 2019-05-24T19:05:00Z Reinildo Cross \n",
"47197 3 1 2019-05-24T19:05:00Z Loïc Remy Pass \n",
"47198 3 1 2019-05-24T19:05:00Z Thiago Mendes Pass \n",
"47199 3 1 2019-05-24T19:05:00Z Jonathan Ikone Pass \n",
"47200 3 1 2019-05-24T19:05:00Z Nicolas Pepe Cross "
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, df_understat_1819_raw\n",
"df_understat_1819_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 19/20"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 309897 \n",
" 15 \n",
" MissedShots \n",
" 0.883 \n",
" 0.713 \n",
" 0.053779 \n",
" Andrew Robertson \n",
" h \n",
" 1688 \n",
" OpenPlay \n",
" 2019 \n",
" LeftFoot \n",
" 11643 \n",
" Liverpool \n",
" Norwich \n",
" 4 \n",
" 1 \n",
" 2019-08-09T20:00:00Z \n",
" Divock Origi \n",
" Pass \n",
" \n",
" \n",
" 1 \n",
" 309898 \n",
" 18 \n",
" Goal \n",
" 0.933 \n",
" 0.367 \n",
" 0.366817 \n",
" Mohamed Salah \n",
" h \n",
" 1250 \n",
" OpenPlay \n",
" 2019 \n",
" LeftFoot \n",
" 11643 \n",
" Liverpool \n",
" Norwich \n",
" 4 \n",
" 1 \n",
" 2019-08-09T20:00:00Z \n",
" Roberto Firmino \n",
" Pass \n",
" \n",
" \n",
" 2 \n",
" 309901 \n",
" 27 \n",
" Goal \n",
" 0.922 \n",
" 0.511 \n",
" 0.105316 \n",
" Virgil van Dijk \n",
" h \n",
" 833 \n",
" FromCorner \n",
" 2019 \n",
" Head \n",
" 11643 \n",
" Liverpool \n",
" Norwich \n",
" 4 \n",
" 1 \n",
" 2019-08-09T20:00:00Z \n",
" Mohamed Salah \n",
" Cross \n",
" \n",
" \n",
" 3 \n",
" 309902 \n",
" 30 \n",
" SavedShot \n",
" 0.878 \n",
" 0.555 \n",
" 0.112044 \n",
" Roberto Firmino \n",
" h \n",
" 482 \n",
" OpenPlay \n",
" 2019 \n",
" LeftFoot \n",
" 11643 \n",
" Liverpool \n",
" Norwich \n",
" 4 \n",
" 1 \n",
" 2019-08-09T20:00:00Z \n",
" Trent Alexander-Arnold \n",
" Cross \n",
" \n",
" \n",
" 4 \n",
" 309904 \n",
" 41 \n",
" Goal \n",
" 0.891 \n",
" 0.530 \n",
" 0.258252 \n",
" Divock Origi \n",
" h \n",
" 484 \n",
" OpenPlay \n",
" 2019 \n",
" Head \n",
" 11643 \n",
" Liverpool \n",
" Norwich \n",
" 4 \n",
" 1 \n",
" 2019-08-09T20:00:00Z \n",
" Trent Alexander-Arnold \n",
" Chipped \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player h_a \\\n",
"0 309897 15 MissedShots 0.883 0.713 0.053779 Andrew Robertson h \n",
"1 309898 18 Goal 0.933 0.367 0.366817 Mohamed Salah h \n",
"2 309901 27 Goal 0.922 0.511 0.105316 Virgil van Dijk h \n",
"3 309902 30 SavedShot 0.878 0.555 0.112044 Roberto Firmino h \n",
"4 309904 41 Goal 0.891 0.530 0.258252 Divock Origi h \n",
"\n",
" player_id situation season shotType match_id h_team a_team \\\n",
"0 1688 OpenPlay 2019 LeftFoot 11643 Liverpool Norwich \n",
"1 1250 OpenPlay 2019 LeftFoot 11643 Liverpool Norwich \n",
"2 833 FromCorner 2019 Head 11643 Liverpool Norwich \n",
"3 482 OpenPlay 2019 LeftFoot 11643 Liverpool Norwich \n",
"4 484 OpenPlay 2019 Head 11643 Liverpool Norwich \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"0 4 1 2019-08-09T20:00:00Z Divock Origi Pass \n",
"1 4 1 2019-08-09T20:00:00Z Roberto Firmino Pass \n",
"2 4 1 2019-08-09T20:00:00Z Mohamed Salah Cross \n",
"3 4 1 2019-08-09T20:00:00Z Trent Alexander-Arnold Cross \n",
"4 4 1 2019-08-09T20:00:00Z Trent Alexander-Arnold Chipped "
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_1920_raw\n",
"df_understat_1920_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 43884 \n",
" 362429 \n",
" 45 \n",
" BlockedShot \n",
" 0.812 \n",
" 0.623 \n",
" 0.042823 \n",
" Houssem Aouar \n",
" a \n",
" 5733 \n",
" OpenPlay \n",
" 2019 \n",
" LeftFoot \n",
" 12982 \n",
" Lille \n",
" Lyon \n",
" 1 \n",
" 0 \n",
" 2020-03-08T19:00:00Z \n",
" Bruno Guimarães \n",
" Pass \n",
" \n",
" \n",
" 43885 \n",
" 362430 \n",
" 48 \n",
" BlockedShot \n",
" 0.913 \n",
" 0.425 \n",
" 0.088323 \n",
" Moussa Dembele \n",
" a \n",
" 7142 \n",
" OpenPlay \n",
" 2019 \n",
" LeftFoot \n",
" 12982 \n",
" Lille \n",
" Lyon \n",
" 1 \n",
" 0 \n",
" 2020-03-08T19:00:00Z \n",
" Karl Toko Ekambi \n",
" Cross \n",
" \n",
" \n",
" 43886 \n",
" 362434 \n",
" 60 \n",
" MissedShots \n",
" 0.844 \n",
" 0.569 \n",
" 0.057904 \n",
" Bruno Guimarães \n",
" a \n",
" 8327 \n",
" SetPiece \n",
" 2019 \n",
" RightFoot \n",
" 12982 \n",
" Lille \n",
" Lyon \n",
" 1 \n",
" 0 \n",
" 2020-03-08T19:00:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
" 43887 \n",
" 362435 \n",
" 91 \n",
" MissedShots \n",
" 0.898 \n",
" 0.377 \n",
" 0.255291 \n",
" Bertrand Traoré \n",
" a \n",
" 695 \n",
" OpenPlay \n",
" 2019 \n",
" LeftFoot \n",
" 12982 \n",
" Lille \n",
" Lyon \n",
" 1 \n",
" 0 \n",
" 2020-03-08T19:00:00Z \n",
" Martin Terrier \n",
" TakeOn \n",
" \n",
" \n",
" 43888 \n",
" 362437 \n",
" 94 \n",
" MissedShots \n",
" 0.734 \n",
" 0.591 \n",
" 0.016734 \n",
" Bruno Guimarães \n",
" a \n",
" 8327 \n",
" OpenPlay \n",
" 2019 \n",
" RightFoot \n",
" 12982 \n",
" Lille \n",
" Lyon \n",
" 1 \n",
" 0 \n",
" 2020-03-08T19:00:00Z \n",
" Karl Toko Ekambi \n",
" Pass \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"43884 362429 45 BlockedShot 0.812 0.623 0.042823 Houssem Aouar \n",
"43885 362430 48 BlockedShot 0.913 0.425 0.088323 Moussa Dembele \n",
"43886 362434 60 MissedShots 0.844 0.569 0.057904 Bruno Guimarães \n",
"43887 362435 91 MissedShots 0.898 0.377 0.255291 Bertrand Traoré \n",
"43888 362437 94 MissedShots 0.734 0.591 0.016734 Bruno Guimarães \n",
"\n",
" h_a player_id situation season shotType match_id h_team a_team \\\n",
"43884 a 5733 OpenPlay 2019 LeftFoot 12982 Lille Lyon \n",
"43885 a 7142 OpenPlay 2019 LeftFoot 12982 Lille Lyon \n",
"43886 a 8327 SetPiece 2019 RightFoot 12982 Lille Lyon \n",
"43887 a 695 OpenPlay 2019 LeftFoot 12982 Lille Lyon \n",
"43888 a 8327 OpenPlay 2019 RightFoot 12982 Lille Lyon \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"43884 1 0 2020-03-08T19:00:00Z Bruno Guimarães Pass \n",
"43885 1 0 2020-03-08T19:00:00Z Karl Toko Ekambi Cross \n",
"43886 1 0 2020-03-08T19:00:00Z NaN None \n",
"43887 1 0 2020-03-08T19:00:00Z Martin Terrier TakeOn \n",
"43888 1 0 2020-03-08T19:00:00Z Karl Toko Ekambi Pass "
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, df_understat_1920_raw\n",
"df_understat_1920_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 20/21"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 376477 \n",
" 6 \n",
" SavedShot \n",
" 0.785 \n",
" 0.249 \n",
" 0.020528 \n",
" Denis Odoi \n",
" h \n",
" 7077 \n",
" OpenPlay \n",
" 2020 \n",
" LeftFoot \n",
" 14086 \n",
" Fulham \n",
" Arsenal \n",
" 0 \n",
" 3 \n",
" 2020-09-12T11:30:00Z \n",
" Ivan Cavaleiro \n",
" Pass \n",
" \n",
" \n",
" 1 \n",
" 376481 \n",
" 9 \n",
" BlockedShot \n",
" 0.933 \n",
" 0.342 \n",
" 0.045429 \n",
" Neeskens Kebano \n",
" h \n",
" 6840 \n",
" OpenPlay \n",
" 2020 \n",
" RightFoot \n",
" 14086 \n",
" Fulham \n",
" Arsenal \n",
" 0 \n",
" 3 \n",
" 2020-09-12T11:30:00Z \n",
" Ivan Cavaleiro \n",
" Cross \n",
" \n",
" \n",
" 2 \n",
" 376487 \n",
" 55 \n",
" MissedShots \n",
" 0.813 \n",
" 0.319 \n",
" 0.020672 \n",
" Aboubakar Kamara \n",
" h \n",
" 4866 \n",
" SetPiece \n",
" 2020 \n",
" RightFoot \n",
" 14086 \n",
" Fulham \n",
" Arsenal \n",
" 0 \n",
" 3 \n",
" 2020-09-12T11:30:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
" 3 \n",
" 376490 \n",
" 66 \n",
" SavedShot \n",
" 0.803 \n",
" 0.655 \n",
" 0.034215 \n",
" Aleksandar Mitrovic \n",
" h \n",
" 773 \n",
" OpenPlay \n",
" 2020 \n",
" RightFoot \n",
" 14086 \n",
" Fulham \n",
" Arsenal \n",
" 0 \n",
" 3 \n",
" 2020-09-12T11:30:00Z \n",
" Franck Zambo \n",
" Pass \n",
" \n",
" \n",
" 4 \n",
" 376494 \n",
" 89 \n",
" MissedShots \n",
" 0.596 \n",
" 0.292 \n",
" 0.005483 \n",
" Bobby Reid \n",
" h \n",
" 6827 \n",
" OpenPlay \n",
" 2020 \n",
" RightFoot \n",
" 14086 \n",
" Fulham \n",
" Arsenal \n",
" 0 \n",
" 3 \n",
" 2020-09-12T11:30:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"0 376477 6 SavedShot 0.785 0.249 0.020528 Denis Odoi \n",
"1 376481 9 BlockedShot 0.933 0.342 0.045429 Neeskens Kebano \n",
"2 376487 55 MissedShots 0.813 0.319 0.020672 Aboubakar Kamara \n",
"3 376490 66 SavedShot 0.803 0.655 0.034215 Aleksandar Mitrovic \n",
"4 376494 89 MissedShots 0.596 0.292 0.005483 Bobby Reid \n",
"\n",
" h_a player_id situation season shotType match_id h_team a_team \\\n",
"0 h 7077 OpenPlay 2020 LeftFoot 14086 Fulham Arsenal \n",
"1 h 6840 OpenPlay 2020 RightFoot 14086 Fulham Arsenal \n",
"2 h 4866 SetPiece 2020 RightFoot 14086 Fulham Arsenal \n",
"3 h 773 OpenPlay 2020 RightFoot 14086 Fulham Arsenal \n",
"4 h 6827 OpenPlay 2020 RightFoot 14086 Fulham Arsenal \n",
"\n",
" h_goals a_goals date player_assisted lastAction \n",
"0 0 3 2020-09-12T11:30:00Z Ivan Cavaleiro Pass \n",
"1 0 3 2020-09-12T11:30:00Z Ivan Cavaleiro Cross \n",
"2 0 3 2020-09-12T11:30:00Z NaN None \n",
"3 0 3 2020-09-12T11:30:00Z Franck Zambo Pass \n",
"4 0 3 2020-09-12T11:30:00Z NaN None "
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the first 5 rows of the raw DataFrame, df_understat_2021_raw\n",
"df_understat_2021_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" h_a \n",
" player_id \n",
" situation \n",
" season \n",
" shotType \n",
" match_id \n",
" h_team \n",
" a_team \n",
" h_goals \n",
" a_goals \n",
" date \n",
" player_assisted \n",
" lastAction \n",
" \n",
" \n",
" \n",
" \n",
" 16755 \n",
" 395525 \n",
" 45 \n",
" SavedShot \n",
" 0.792 \n",
" 0.273 \n",
" 0.016651 \n",
" Kenny Lala \n",
" a \n",
" 5975 \n",
" OpenPlay \n",
" 2020 \n",
" RightFoot \n",
" 15924 \n",
" Paris Saint Germain \n",
" Strasbourg \n",
" 4 \n",
" 0 \n",
" 2020-12-23T20:00:00Z \n",
" NaN \n",
" None \n",
" \n",
" \n",
" 16756 \n",
" 395527 \n",
" 55 \n",
" BlockedShot \n",
" 0.803 \n",
" 0.645 \n",
" 0.028917 \n",
" Lionel Carole \n",
" a \n",
" 6318 \n",
" OpenPlay \n",
" 2020 \n",
" LeftFoot \n",
" 15924 \n",
" Paris Saint Germain \n",
" Strasbourg \n",
" 4 \n",
" 0 \n",
" 2020-12-23T20:00:00Z \n",
" Jean-Ricner Bellegarde \n",
" Pass \n",
" \n",
" \n",
" 16757 \n",
" 395529 \n",
" 65 \n",
" MissedShots \n",
" 0.935 \n",
" 0.485 \n",
" 0.088725 \n",
" Mohamed Simakan \n",
" a \n",
" 7551 \n",
" FromCorner \n",
" 2020 \n",
" RightFoot \n",
" 15924 \n",
" Paris Saint Germain \n",
" Strasbourg \n",
" 4 \n",
" 0 \n",
" 2020-12-23T20:00:00Z \n",
" NaN \n",
" Aerial \n",
" \n",
" \n",
" 16758 \n",
" 395532 \n",
" 74 \n",
" MissedShots \n",
" 0.793 \n",
" 0.649 \n",
" 0.025098 \n",
" Sanjin Prcic \n",
" a \n",
" 1932 \n",
" OpenPlay \n",
" 2020 \n",
" RightFoot \n",
" 15924 \n",
" Paris Saint Germain \n",
" Strasbourg \n",
" 4 \n",
" 0 \n",
" 2020-12-23T20:00:00Z \n",
" NaN \n",
" BallRecovery \n",
" \n",
" \n",
" 16759 \n",
" 395534 \n",
" 85 \n",
" BlockedShot \n",
" 0.698 \n",
" 0.312 \n",
" 0.008228 \n",
" Kenny Lala \n",
" a \n",
" 5975 \n",
" OpenPlay \n",
" 2020 \n",
" RightFoot \n",
" 15924 \n",
" Paris Saint Germain \n",
" Strasbourg \n",
" 4 \n",
" 0 \n",
" 2020-12-23T20:00:00Z \n",
" Jean Eudes Aholou \n",
" Pass \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"16755 395525 45 SavedShot 0.792 0.273 0.016651 Kenny Lala \n",
"16756 395527 55 BlockedShot 0.803 0.645 0.028917 Lionel Carole \n",
"16757 395529 65 MissedShots 0.935 0.485 0.088725 Mohamed Simakan \n",
"16758 395532 74 MissedShots 0.793 0.649 0.025098 Sanjin Prcic \n",
"16759 395534 85 BlockedShot 0.698 0.312 0.008228 Kenny Lala \n",
"\n",
" h_a player_id situation season shotType match_id \\\n",
"16755 a 5975 OpenPlay 2020 RightFoot 15924 \n",
"16756 a 6318 OpenPlay 2020 LeftFoot 15924 \n",
"16757 a 7551 FromCorner 2020 RightFoot 15924 \n",
"16758 a 1932 OpenPlay 2020 RightFoot 15924 \n",
"16759 a 5975 OpenPlay 2020 RightFoot 15924 \n",
"\n",
" h_team a_team h_goals a_goals \\\n",
"16755 Paris Saint Germain Strasbourg 4 0 \n",
"16756 Paris Saint Germain Strasbourg 4 0 \n",
"16757 Paris Saint Germain Strasbourg 4 0 \n",
"16758 Paris Saint Germain Strasbourg 4 0 \n",
"16759 Paris Saint Germain Strasbourg 4 0 \n",
"\n",
" date player_assisted lastAction \n",
"16755 2020-12-23T20:00:00Z NaN None \n",
"16756 2020-12-23T20:00:00Z Jean-Ricner Bellegarde Pass \n",
"16757 2020-12-23T20:00:00Z NaN Aerial \n",
"16758 2020-12-23T20:00:00Z NaN BallRecovery \n",
"16759 2020-12-23T20:00:00Z Jean Eudes Aholou Pass "
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Display the last 5 rows of the raw DataFrame, df_understat_12021_raw\n",
"df_understat_2021_raw.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The datasets have twenty features (columns). Full details of these attributes can be found in the [Data Dictionary](section3.3.1)."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"id int64\n",
"minute int64\n",
"result object\n",
"X float64\n",
"Y float64\n",
"xG float64\n",
"player object\n",
"h_a object\n",
"player_id int64\n",
"situation object\n",
"season int64\n",
"shotType object\n",
"match_id int64\n",
"h_team object\n",
"a_team object\n",
"h_goals int64\n",
"a_goals int64\n",
"date object\n",
"player_assisted object\n",
"lastAction object\n",
"dtype: object"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Data types of the features of the raw DataFrame, df_understat_2021_raw.\n",
"df_understat_2021_raw.dtypes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All six of the columns have the object data type. Full details of these attributes and their data types can be found in the [Data Dictionary](section3.3.1)."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"RangeIndex: 16760 entries, 0 to 16759\n",
"Data columns (total 20 columns):\n",
" # Column Non-Null Count Dtype \n",
"--- ------ -------------- ----- \n",
" 0 id 16760 non-null int64 \n",
" 1 minute 16760 non-null int64 \n",
" 2 result 16760 non-null object \n",
" 3 X 16760 non-null float64\n",
" 4 Y 16760 non-null float64\n",
" 5 xG 16760 non-null float64\n",
" 6 player 16760 non-null object \n",
" 7 h_a 16760 non-null object \n",
" 8 player_id 16760 non-null int64 \n",
" 9 situation 16760 non-null object \n",
" 10 season 16760 non-null int64 \n",
" 11 shotType 16760 non-null object \n",
" 12 match_id 16760 non-null int64 \n",
" 13 h_team 16760 non-null object \n",
" 14 a_team 16760 non-null object \n",
" 15 h_goals 16760 non-null int64 \n",
" 16 a_goals 16760 non-null int64 \n",
" 17 date 16760 non-null object \n",
" 18 player_assisted 12339 non-null object \n",
" 19 lastAction 16760 non-null object \n",
"dtypes: float64(3), int64(7), object(10)\n",
"memory usage: 2.6+ MB\n"
]
}
],
"source": [
"# Info for the raw DataFrame, df_understat_2021_raw\n",
"df_understat_2021_raw.info()"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" X \n",
" Y \n",
" xG \n",
" player_id \n",
" season \n",
" match_id \n",
" h_goals \n",
" a_goals \n",
" \n",
" \n",
" \n",
" \n",
" count \n",
" 16760.000000 \n",
" 16760.000000 \n",
" 16760.000000 \n",
" 16760.000000 \n",
" 16760.000000 \n",
" 16760.000000 \n",
" 16760.0 \n",
" 16760.000000 \n",
" 16760.000000 \n",
" 16760.000000 \n",
" \n",
" \n",
" mean \n",
" 385974.263305 \n",
" 48.555131 \n",
" 0.848198 \n",
" 0.507376 \n",
" 0.118375 \n",
" 4339.029415 \n",
" 2020.0 \n",
" 14987.373986 \n",
" 1.544690 \n",
" 1.453998 \n",
" \n",
" \n",
" std \n",
" 5697.376414 \n",
" 26.653520 \n",
" 0.092492 \n",
" 0.125784 \n",
" 0.171406 \n",
" 2898.684972 \n",
" 0.0 \n",
" 611.360956 \n",
" 1.354088 \n",
" 1.192357 \n",
" \n",
" \n",
" min \n",
" 375453.000000 \n",
" 0.000000 \n",
" 0.004000 \n",
" 0.000000 \n",
" 0.000000 \n",
" 3.000000 \n",
" 2020.0 \n",
" 13977.000000 \n",
" 0.000000 \n",
" 0.000000 \n",
" \n",
" \n",
" 25% \n",
" 381067.750000 \n",
" 26.000000 \n",
" 0.789000 \n",
" 0.419000 \n",
" 0.025811 \n",
" 1491.750000 \n",
" 2020.0 \n",
" 14491.000000 \n",
" 1.000000 \n",
" 1.000000 \n",
" \n",
" \n",
" 50% \n",
" 385991.500000 \n",
" 49.000000 \n",
" 0.868000 \n",
" 0.503000 \n",
" 0.053571 \n",
" 4234.000000 \n",
" 2020.0 \n",
" 14916.000000 \n",
" 1.000000 \n",
" 1.000000 \n",
" \n",
" \n",
" 75% \n",
" 390978.250000 \n",
" 71.000000 \n",
" 0.911000 \n",
" 0.598000 \n",
" 0.100111 \n",
" 7006.000000 \n",
" 2020.0 \n",
" 15508.000000 \n",
" 2.000000 \n",
" 2.000000 \n",
" \n",
" \n",
" max \n",
" 395596.000000 \n",
" 100.000000 \n",
" 0.997000 \n",
" 0.995000 \n",
" 0.978288 \n",
" 9205.000000 \n",
" 2020.0 \n",
" 15925.000000 \n",
" 8.000000 \n",
" 7.000000 \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute X Y xG \\\n",
"count 16760.000000 16760.000000 16760.000000 16760.000000 16760.000000 \n",
"mean 385974.263305 48.555131 0.848198 0.507376 0.118375 \n",
"std 5697.376414 26.653520 0.092492 0.125784 0.171406 \n",
"min 375453.000000 0.000000 0.004000 0.000000 0.000000 \n",
"25% 381067.750000 26.000000 0.789000 0.419000 0.025811 \n",
"50% 385991.500000 49.000000 0.868000 0.503000 0.053571 \n",
"75% 390978.250000 71.000000 0.911000 0.598000 0.100111 \n",
"max 395596.000000 100.000000 0.997000 0.995000 0.978288 \n",
"\n",
" player_id season match_id h_goals a_goals \n",
"count 16760.000000 16760.0 16760.000000 16760.000000 16760.000000 \n",
"mean 4339.029415 2020.0 14987.373986 1.544690 1.453998 \n",
"std 2898.684972 0.0 611.360956 1.354088 1.192357 \n",
"min 3.000000 2020.0 13977.000000 0.000000 0.000000 \n",
"25% 1491.750000 2020.0 14491.000000 1.000000 1.000000 \n",
"50% 4234.000000 2020.0 14916.000000 1.000000 1.000000 \n",
"75% 7006.000000 2020.0 15508.000000 2.000000 2.000000 \n",
"max 9205.000000 2020.0 15925.000000 8.000000 7.000000 "
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Description of the raw DataFrame, df_understat_2021_raw, showing some summary statistics for each numberical column in the DataFrame\n",
"df_understat_2021_raw.describe()"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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p8cvfvGL2G677db73IF1fvlNN90U48ePj0ceeSQ++tGPtv3M/PnzY8WKFXHeeef1F3EREXvvvXd84Qtf6C/GUp566qkoiiJ23HHHOO200/pfX7x4cTz66KNx/PHHrzXVtskmm8QZZ5wREyZMiBdffDEiIpYuXRp/+MMf4qCDDlrr933gAx+ICRMmxIMPPhgPP/xwnT8ZAAAAAADgTT3xxBMxadKkWLZs2Vqv/+Y3v4menp648sorY9ddd41x48bFSSedFNdff31DSXkzDzzwQCxbtiwuvfTSGDVqVIwdOzZOP/30WLhwYdx9993x9NNPx0UXXRQ777xznHzyyfGhD30o5s+f/6bPrVXGzZ49O7bZZpuYO3dufOYzn2n7mbvuuis22WSTtmXdWWedFTNnzlzv77jiiivi9ddfj3POOSeGDh261nMjIg455JB1fubII4+Miy66KLbeeuuIiLjnnnsiIuIjH/nIOp9d89qb3aoDAAAAAACo689//nN87GMfix//+Mdrvb58+fLYaaedYtNNN+1/bdddd40HH3wwXn/99f/vmLWtWrUq27P/+Mc/Zn3+f2vkyJFx3XXXxcYbb9z/2oABA6K3tzfuv//+2H333eM973lP/3tjxoypNRFba03lhRdeGPvvv38MGjQoli5dus77fX198eSTT8auu+4aPT09MWvWrPjtb3/bf/vtq1/96non4+6777648847Y999911nt+aakc7tt98+rr766rj11lujp6cnRo4cGV/60pfi05/+dP9nly9fHhHRdhxwm222iYhomx8AAAAAAOA/MXny5Lavb7755tHT0xOrVq2KQYMGRcS/Tn698cYb8fLLL6+1ZbBTrFq1Kr72ta9le/7FF18cu+22W3zrW9/q/046yfDhw/vPqEX865Ta3LlzY8yYMdHT0xMjRoxY6/ObbbZZPP/882/63Fpl3Mc//vH1vv/yyy/Hq6++GitXroxjjjkmhg0bFkcccUT09PTEr3/96zjuuONi9uzZseeee7b9+RtuuCEiIj7/+c+v897f/va3GDp0aEyfPj2WLFkS48aNiwEDBsQdd9wRp59+elxwwQVx3HHHRUTEP/7xj4iIeN/73rfOc9773vf2ZwUAAAAAoJ5Wq9V0hK5QFEXTEegwBx54YFx88cUxa9asmD59ejzzzDNx0003RUR07GTc4sWLs577eu211+Khhx6KxYsXx3777Zft97xVLr300nj44Ydj/vz5ceONN8aQIUPWen/o0KG1/lvWKuPezGuvvRYREQ899FDst99+8b3vfS/e9a53RUTEnXfeGaeeemp8/etfj5///Ofr/Oxzzz0XixYtipEjR8YnP/nJts/u7e2Nxx57LG655ZbYaqutIiLilFNOiaOOOiouu+yyOPjgg2PzzTfv/4P/fc3lGmte6+3tbfs3OEK64Xxn9fmuNozvqz7f1YbxfdXnu6rPd7VhfF/1+a42jO+rPt/VhvF91ee72jC+r/p8VxvG91Wf76o+39WG8X2xxvDhw+Pqq6+OGTNmxA033BCbbbZZnHTSSfHNb35zrVWHneTxxx+PFStWrPXagAED4sQTT4wpU6Zs8PNmz54dN910U/T19fW/tnLlynjiiSc6uozr6+uLSy65JObNmxdXX3117LLLLrHRRhvFK6+8stbnent7+/uw9XlLyrgBAwb0/+8ZM2as9YsPOuigGDt2bCxevDiWLl0aO+6441o/u2DBgli1alUcffTRaz3n/z77pJNO6i/iIiK23XbbmDJlSlxzzTWxaNGimDRpUv/vbddCrinhhg0b9p//oQAAAAAAADUdcMAB8bvf/S56enpis802i9///vfx/ve/f62bZJ1k6tSpMXXq1I593v+H1atXx7nnnhsLFy6Mq666KsaNGxcREVtuuWU88sgja332hRdeiC222OJNnznwrQi2ZgXkkCFDYpdddlnn/TX34pYtW7bOe4sWLYqIiEMOOWS9z95jjz3Wee+DH/zgWs9ds56y3SrKNa+teR4AAAAAAEAuTz75ZEyZMiVWrVoVI0aMiEGDBsWdd94ZY8eObToa63HZZZfFwoUL45prromDDz64//W99947HnnkkXj11Vf7X7v33ntjn332edNnviVl3LBhw2LEiBGxatWqWL169Trvv/HGG/2f+3cvvfRSPPDAA7HHHnvEtttu2/bZO+ywQ0S0n3Zb89w1E3E77bRTREQ888wz63x2zWtrPgMAAAAAAJDLdtttF08//XRcddVVsXz58rj55pvjlltuiZNPPrnpaCRUVRU/+MEPYvr06TF69Ojo6enp/2fs2LGx9dZbx4wZM+Lxxx+P6667Lu6///445phj3vS5b0kZFxGx7777xurVq+Oee+5Z570lS5bE4MGDY9SoUWu9/sADD0RfX1/su+++631uRMTdd9+9znsPPvhgRPzvhNyYMWMiItpmWLx4cURErYYSAAAAAADgvzF06NC49tpr409/+lOMHz8+fvrTn8Z3v/vdGD16dNPRSLj99tsjIuLKK6+MAw44YK1/+vr64tprr42XXnopJk6cGLfeemt85zvfSQ6b/bu35GZcRMSkSZPitttui8svvzzmzJnTf3zwtttui6qq4lOf+lQMHz58rZ956KGHIiJizz33TD730EMPjVmzZsWcOXNiwoQJ/YXe0qVLY968ebHFFlvEgQceGBH/apk//OEPx+233x4nnHBC/3Mfe+yxWLBgQYwePbrtuksAAAAAAID/1qOPPrrWv++1114xf/78htKwoc4+++w4++yzk+/vsMMOMXfu3A1+7ltWxu23334xZcqUmDNnTowfPz4OPvjgeP755+OOO+6IzTffPGbOnLnOzyxfvjwi/ncVZTubbrppXHTRRXHWWWfF0UcfHYcffngMHDgwfvWrX8WKFSvi8ssvj6FDh/Z//txzz43PfvazMXXq1Bg/fnwMGjQoFixYEH19fXHBBRe8VX8uAAAAAAAAvKm3rIyLiDjvvPNi9913j7lz58a8efNi4403jiOOOCLOOOOM2Gabbdb5/N///veIiNhyyy3X+9xDDz00RowYEddee23cdtttEfGvNvm0005bZ8Xl6NGj4+abb45Zs2bFwoULY8iQIbHPPvvEGWecsd4JPAAAAAAAAHirDejr6+trOgQAAAAAAAC8HQ1sOgAAAAAAAAC8XSnjAAAAAAAAIBNlHAAAAAAAAGSijAMAAAAAAIBMlHEAAAAAAACQiTIOAAAAAAAAMlHGAQAAAAAAsaK2ngAAACVJREFUQCbKOAAAAAAAAMhEGQcAAAAAAACZKOMAAAAAAAAgk/8B73lMR8uVf1cAAAAASUVORK5CYII=\n",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Plot visualisation of the missing values for each feature of the raw DataFrame, df_understat_2021_raw\n",
"msno.matrix(df_understat_2021_raw, figsize = (30, 7))"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"player_assisted 4421\n",
"dtype: int64"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Counts of missing values\n",
"tm_null_value_stats = df_understat_2021_raw.isnull().sum(axis=0)\n",
"tm_null_value_stats[tm_null_value_stats != 0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The visualisation shows us very quickly that the only column that has missing vlaues is the `player_assisted` column, that must be for goals where there was no assist. Our datasets are therefore complete and ready to be engineered."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Data Engineering "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.1. Introduction \n",
"Before we answer the questions in the brief through [Exploratory Data Analysis (EDA)](#section5), we'll first need to clean and wrangle the datasets to a form that meet our needs."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.2. Assign Raw DataFrames to New Engineered DataFrames "
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
"# Assign Raw DataFrames to new Engineered DataFrames\n",
"df_understat_1415 = df_understat_1415_raw\n",
"df_understat_1516 = df_understat_1516_raw\n",
"df_understat_1617 = df_understat_1617_raw\n",
"df_understat_1718 = df_understat_1718_raw\n",
"df_understat_1819 = df_understat_1819_raw\n",
"df_understat_1920 = df_understat_1920_raw\n",
"df_understat_2021 = df_understat_2021_raw"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.2. Add Season Column to Each Dataset "
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": [
"df_understat_1415['Season'] = '14/15'\n",
"df_understat_1516['Season'] = '15/16'\n",
"df_understat_1617['Season'] = '16/17'\n",
"df_understat_1718['Season'] = '17/18'\n",
"df_understat_1819['Season'] = '18/19'\n",
"df_understat_1920['Season'] = '19/20'\n",
"df_understat_2021['Season'] = '20/21'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.3. Union the Datasets for Individual Seasons "
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"# Union the individual datasets for 14/15, 15/16, 16/17, 17/18, 18/19, 19/20, and 20/21 \n",
"df_understat_combined = pd.concat([df_understat_1415, df_understat_1516, df_understat_1617, df_understat_1718, df_understat_1819, df_understat_1920, df_understat_2021])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.4. Export Raw DataFrame "
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
"# Export DataFrame as a CSV file\n",
"\n",
"## Export a copy to the 'archive' subfolder of the Understat folder, including the date\n",
"df_understat_combined.to_csv(data_dir_understat + '/raw/combined/archive/' + f'understat_combined_big5_last_updated_{today}.csv', index=None, header=True)\n",
"\n",
"## Export another copy to the Understat folder called 'latest' (can be overwritten)\n",
"df_understat_combined.to_csv(data_dir_understat + '/raw/combined/archive/' + f'understat_combined_big5_last_updated_latest.csv', index=None, header=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.5. Drop old `season` column "
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined = df_understat_combined.drop(['season'], axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.6. Rename Columns "
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
"# Rename columns\n",
"df_understat_combined = df_understat_combined.rename({'id': 'id',\n",
" 'minute': 'minute',\n",
" 'result': 'result',\n",
" 'X': 'X',\n",
" 'Y': 'Y',\n",
" 'xG': 'xG',\n",
" 'player': 'player',\n",
" 'h_a': 'home_away',\n",
" 'player_id': 'player_id',\n",
" 'situation': 'situation',\n",
" 'shotType': 'shot_type',\n",
" 'match_id': 'match_id',\n",
" 'h_team': 'home_team',\n",
" 'a_team': 'away_team',\n",
" 'h_goals': 'home_goals',\n",
" 'a_goals': 'away_goals',\n",
" 'date': 'kick_off',\n",
" 'player_assisted': 'player_assisted',\n",
" 'lastAction': 'last_action',\n",
" 'Season': 'season'}, axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.7. Clean Date "
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [],
"source": [
"# Clean date column\n",
"\n",
"## Convert 'kick_off' column to datetime\n",
"df_understat_combined['kick_off'] = pd.to_datetime(df_understat_combined['kick_off']).dt.strftime('%d-%m-%y %H:%M:%S')\n",
"\n",
"## Create 'date' column from 'kick_off column'\n",
"df_understat_combined['date'] = pd.to_datetime(df_understat_combined['kick_off']).dt.strftime('%d-%m-%Y')\n",
"\n",
"## Convert from Object to Datetime\n",
"df_understat_combined['kick_off'] = pd.to_datetime(df_understat_combined['kick_off'])\n",
"df_understat_combined['date'] = pd.to_datetime(df_understat_combined['date'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.8. Create `Year`, `Month` and `Day` columns "
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['year'] = pd.DatetimeIndex(df_understat_combined['date']).year\n",
"df_understat_combined['month'] = pd.DatetimeIndex(df_understat_combined['date']).month\n",
"df_understat_combined['day'] = pd.DatetimeIndex(df_understat_combined['date']).day"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.9. Convert X and Y Coordinates to 120 by 80 coordinates "
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['X_120'] = df_understat_combined['X'] * 120\n",
"df_understat_combined['Y_80'] = df_understat_combined['Y'] * 80"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.10. Clean column contents "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### `home_away` "
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['h', 'a'], dtype=object)"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined['home_away'].unique()"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['home_away'] = df_understat_combined['home_away'].map({'h': 'Home',\n",
" 'a': 'Away'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### `result`"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['SavedShot', 'BlockedShot', 'MissedShots', 'Goal', 'ShotOnPost',\n",
" 'OwnGoal'], dtype=object)"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined['result'].unique()"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['result'] = df_understat_combined['result'].map({'SavedShot': 'Saved Shot',\n",
" 'BlockedShot': 'Blocked Shots',\n",
" 'MissedShots': 'Missed Shots',\n",
" 'Goal': 'Goal',\n",
" 'ShotOnPost': ' Shot on Post',\n",
" 'OwnGoal': 'Own Goal'})"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" home_away \n",
" player_id \n",
" situation \n",
" ... \n",
" kick_off \n",
" player_assisted \n",
" last_action \n",
" season \n",
" date \n",
" year \n",
" month \n",
" day \n",
" X_120 \n",
" Y_80 \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 14511 \n",
" 12 \n",
" Saved Shot \n",
" 0.728 \n",
" 0.501 \n",
" 0.018741 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" OpenPlay \n",
" ... \n",
" 2014-08-16 12:45:00 \n",
" Darren Fletcher \n",
" Pass \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 87.360004 \n",
" 40.079999 \n",
" \n",
" \n",
" 1 \n",
" 14512 \n",
" 16 \n",
" Blocked Shots \n",
" 0.789 \n",
" 0.336 \n",
" 0.015598 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" OpenPlay \n",
" ... \n",
" 2014-08-16 12:45:00 \n",
" Chicharito \n",
" TakeOn \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 94.680002 \n",
" 26.879999 \n",
" \n",
" \n",
" 2 \n",
" 14513 \n",
" 25 \n",
" Saved Shot \n",
" 0.914 \n",
" 0.188 \n",
" 0.064923 \n",
" Juan Mata \n",
" Home \n",
" 554 \n",
" DirectFreekick \n",
" ... \n",
" 2014-08-16 12:45:00 \n",
" NaN \n",
" Standard \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 109.680002 \n",
" 15.039999 \n",
" \n",
" \n",
" 3 \n",
" 14514 \n",
" 26 \n",
" Saved Shot \n",
" 0.920 \n",
" 0.482 \n",
" 0.057788 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" OpenPlay \n",
" ... \n",
" 2014-08-16 12:45:00 \n",
" Ashley Young \n",
" Aerial \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 110.400000 \n",
" 38.560001 \n",
" \n",
" \n",
" 4 \n",
" 14516 \n",
" 33 \n",
" Missed Shots \n",
" 0.922 \n",
" 0.590 \n",
" 0.048801 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" FromCorner \n",
" ... \n",
" 2014-08-16 12:45:00 \n",
" Juan Mata \n",
" Cross \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 110.639996 \n",
" 47.200000 \n",
" \n",
" \n",
"
\n",
"
5 rows × 26 columns
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"0 14511 12 Saved Shot 0.728 0.501 0.018741 Wayne Rooney \n",
"1 14512 16 Blocked Shots 0.789 0.336 0.015598 Wayne Rooney \n",
"2 14513 25 Saved Shot 0.914 0.188 0.064923 Juan Mata \n",
"3 14514 26 Saved Shot 0.920 0.482 0.057788 Wayne Rooney \n",
"4 14516 33 Missed Shots 0.922 0.590 0.048801 Wayne Rooney \n",
"\n",
" home_away player_id situation ... kick_off \\\n",
"0 Home 629 OpenPlay ... 2014-08-16 12:45:00 \n",
"1 Home 629 OpenPlay ... 2014-08-16 12:45:00 \n",
"2 Home 554 DirectFreekick ... 2014-08-16 12:45:00 \n",
"3 Home 629 OpenPlay ... 2014-08-16 12:45:00 \n",
"4 Home 629 FromCorner ... 2014-08-16 12:45:00 \n",
"\n",
" player_assisted last_action season date year month day X_120 \\\n",
"0 Darren Fletcher Pass 14/15 2014-08-16 2014 8 16 87.360004 \n",
"1 Chicharito TakeOn 14/15 2014-08-16 2014 8 16 94.680002 \n",
"2 NaN Standard 14/15 2014-08-16 2014 8 16 109.680002 \n",
"3 Ashley Young Aerial 14/15 2014-08-16 2014 8 16 110.400000 \n",
"4 Juan Mata Cross 14/15 2014-08-16 2014 8 16 110.639996 \n",
"\n",
" Y_80 \n",
"0 40.079999 \n",
"1 26.879999 \n",
"2 15.039999 \n",
"3 38.560001 \n",
"4 47.200000 \n",
"\n",
"[5 rows x 26 columns]"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### `situation`"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['OpenPlay', 'DirectFreekick', 'FromCorner', 'Penalty', 'SetPiece'],\n",
" dtype=object)"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined['situation'].unique()"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['situation'] = df_understat_combined['situation'].map({'OpenPlay': 'Open Play',\n",
" 'DirectFreekick': 'Direct Freekick',\n",
" 'FromCorner': 'From Corner',\n",
" 'Penalty': 'Penalty',\n",
" 'SetPiece': 'Set Piece'\n",
" })"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### `\tlast_action`"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array(['Pass', 'TakeOn', 'Standard', 'Aerial', 'Cross', 'Rebound',\n",
" 'HeadPass', 'BallRecovery', 'BallTouch', 'None', 'Throughball',\n",
" 'Goal', 'Chipped', 'LayOff', 'Dispossessed', 'Tackle', 'Save',\n",
" 'Foul', 'BlockedPass', 'Challenge', 'End', 'CornerAwarded',\n",
" 'Interception', 'GoodSkill', 'Card', 'Clearance', 'Punch',\n",
" 'OffsidePass', 'SubstitutionOn', 'KeeperPickup', 'CrossNotClaimed',\n",
" 'FormationChange', 'ChanceMissed', 'ShieldBallOpp', 'Error',\n",
" 'KeeperSweeper', 'PenaltyFaced', 'Start', 'OffsideProvoked',\n",
" 'Smother', 'SubstitutionOff'], dtype=object)"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined['last_action'].unique()"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['last_action'] = df_understat_combined['last_action'].map({'Pass': 'Pass',\n",
" 'TakeOn': 'Take On',\n",
" 'Standard': 'Standard',\n",
" 'Aerial': 'Aerial',\n",
" 'Cross': 'Cross',\n",
" 'Rebound': 'Rebound',\n",
" 'HeadPass': 'Head Pass',\n",
" 'BallRecovery': 'Ball Recovery',\n",
" 'BallTouch': 'Ball Touch',\n",
" 'None': 'None',\n",
" 'Throughball': 'Throughball',\n",
" 'Goal': 'Goal',\n",
" 'Chipped': 'Chipped',\n",
" 'LayOff': 'Lay Off',\n",
" 'Dispossessed': 'Dispossessed',\n",
" 'Tackle': 'Tackle',\n",
" 'Save': 'Save',\n",
" 'Foul': 'Foul',\n",
" 'BlockedPass': 'Blocked Pass',\n",
" 'Challenge': 'Challenge',\n",
" 'End': 'End',\n",
" 'CornerAwarded': 'Corner Awarded',\n",
" 'Interception': 'Interception',\n",
" 'GoodSkill': 'Good Skill',\n",
" 'Card': 'Card',\n",
" 'Clearance': 'Clearance',\n",
" 'Punch': 'Punch',\n",
" 'OffsidePass': 'Offside Pass',\n",
" 'SubstitutionOn': 'Substitution On',\n",
" 'KeeperPickup': 'Keeper Pickup',\n",
" 'CrossNotClaimed': 'Cross Not Claimed',\n",
" 'FormationChange': 'Formation Change',\n",
" 'ChanceMissed': 'Chance Missed',\n",
" 'ShieldBallOpp': 'Shield Ball Opp',\n",
" 'Error': 'Error',\n",
" 'KeeperSweeper': 'Keeper Sweeper',\n",
" 'PenaltyFaced': 'Penalty Faced',\n",
" 'Start': 'Start',\n",
" 'OffsideProvoked': 'Offside Provoked',\n",
" 'Smother': 'Smother',\n",
" 'SubstitutionOff': 'Substitution Off'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.11. Add League Name and Country to the DataFrames "
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
"# COMMENTED OUT AS EXPORTED THIS RECENTLY - 05/09/2020\n",
"\n",
"# Create DataFrame of Home and Away teams\n",
"\n",
"## All unique Home and Away teams\n",
"lst_home_teams = list(df_understat_combined['home_team'].unique())\n",
"lst_away_teams = list(df_understat_combined['away_team'].unique())\n",
"\n",
"## DataFrames of Home and Away teams\n",
"df_home_teams = pd.DataFrame(lst_home_teams)\n",
"df_away_teams = pd.DataFrame(lst_away_teams)\n",
"\n",
"## Concatenate DataFrames\n",
"df_teams = pd.concat([df_home_teams, df_away_teams], ignore_index=True)\n",
"\n",
"## Export DataFrame\n",
"df_teams.to_csv(data_dir + '/teams_big5_1415_2021_raw.csv', index=None, header=True)"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"df_teams = pd.read_csv(data_dir + '/teams/teams_big5_1415_2021.csv')"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" team_name \n",
" league_name \n",
" league_country \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" AC Milan \n",
" Seria A \n",
" Italy \n",
" \n",
" \n",
" 1 \n",
" Alaves \n",
" La Liga \n",
" Spain \n",
" \n",
" \n",
" 2 \n",
" Almeria \n",
" La Liga \n",
" Spain \n",
" \n",
" \n",
" 3 \n",
" Amiens \n",
" Ligue 1 \n",
" France \n",
" \n",
" \n",
" 4 \n",
" Angers \n",
" Ligue 1 \n",
" France \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" team_name league_name league_country\n",
"0 AC Milan Seria A Italy\n",
"1 Alaves La Liga Spain\n",
"2 Almeria La Liga Spain\n",
"3 Amiens Ligue 1 France\n",
"4 Angers Ligue 1 France"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_teams.head()"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined = pd.merge(df_understat_combined, df_teams, left_on='home_team', right_on='team_name')"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" home_away \n",
" player_id \n",
" situation \n",
" ... \n",
" season \n",
" date \n",
" year \n",
" month \n",
" day \n",
" X_120 \n",
" Y_80 \n",
" team_name \n",
" league_name \n",
" league_country \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 14511 \n",
" 12 \n",
" Saved Shot \n",
" 0.728 \n",
" 0.501 \n",
" 0.018741 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" Open Play \n",
" ... \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 87.360004 \n",
" 40.079999 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" \n",
" \n",
" 1 \n",
" 14512 \n",
" 16 \n",
" Blocked Shots \n",
" 0.789 \n",
" 0.336 \n",
" 0.015598 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" Open Play \n",
" ... \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 94.680002 \n",
" 26.879999 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" \n",
" \n",
" 2 \n",
" 14513 \n",
" 25 \n",
" Saved Shot \n",
" 0.914 \n",
" 0.188 \n",
" 0.064923 \n",
" Juan Mata \n",
" Home \n",
" 554 \n",
" Direct Freekick \n",
" ... \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 109.680002 \n",
" 15.039999 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" \n",
" \n",
" 3 \n",
" 14514 \n",
" 26 \n",
" Saved Shot \n",
" 0.920 \n",
" 0.482 \n",
" 0.057788 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" Open Play \n",
" ... \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 110.400000 \n",
" 38.560001 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" \n",
" \n",
" 4 \n",
" 14516 \n",
" 33 \n",
" Missed Shots \n",
" 0.922 \n",
" 0.590 \n",
" 0.048801 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" From Corner \n",
" ... \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 110.639996 \n",
" 47.200000 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" \n",
" \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" ... \n",
" \n",
" \n",
" 290322 \n",
" 395268 \n",
" 72 \n",
" Goal \n",
" 0.885 \n",
" 0.500 \n",
" 0.761299 \n",
" Domenico Criscito \n",
" Away \n",
" 3065 \n",
" Penalty \n",
" ... \n",
" 20/21 \n",
" 2020-12-23 \n",
" 2020 \n",
" 12 \n",
" 23 \n",
" 106.200000 \n",
" 40.000000 \n",
" Spezia \n",
" Seria A \n",
" Italy \n",
" \n",
" \n",
" 290323 \n",
" 395269 \n",
" 78 \n",
" Saved Shot \n",
" 0.937 \n",
" 0.434 \n",
" 0.041579 \n",
" Gianluca Scamacca \n",
" Away \n",
" 6253 \n",
" From Corner \n",
" ... \n",
" 20/21 \n",
" 2020-12-23 \n",
" 2020 \n",
" 12 \n",
" 23 \n",
" 112.439996 \n",
" 34.720001 \n",
" Spezia \n",
" Seria A \n",
" Italy \n",
" \n",
" \n",
" 290324 \n",
" 395270 \n",
" 80 \n",
" Saved Shot \n",
" 0.836 \n",
" 0.493 \n",
" 0.080786 \n",
" Mattia Destro \n",
" Away \n",
" 1580 \n",
" Open Play \n",
" ... \n",
" 20/21 \n",
" 2020-12-23 \n",
" 2020 \n",
" 12 \n",
" 23 \n",
" 100.319998 \n",
" 39.439999 \n",
" Spezia \n",
" Seria A \n",
" Italy \n",
" \n",
" \n",
" 290325 \n",
" 395274 \n",
" 91 \n",
" Saved Shot \n",
" 0.867 \n",
" 0.276 \n",
" 0.235170 \n",
" Gianluca Scamacca \n",
" Away \n",
" 6253 \n",
" Open Play \n",
" ... \n",
" 20/21 \n",
" 2020-12-23 \n",
" 2020 \n",
" 12 \n",
" 23 \n",
" 104.039996 \n",
" 22.080000 \n",
" Spezia \n",
" Seria A \n",
" Italy \n",
" \n",
" \n",
" 290326 \n",
" 395275 \n",
" 92 \n",
" Missed Shots \n",
" 0.764 \n",
" 0.673 \n",
" 0.025288 \n",
" Gianluca Scamacca \n",
" Away \n",
" 6253 \n",
" Open Play \n",
" ... \n",
" 20/21 \n",
" 2020-12-23 \n",
" 2020 \n",
" 12 \n",
" 23 \n",
" 91.680002 \n",
" 53.840002 \n",
" Spezia \n",
" Seria A \n",
" Italy \n",
" \n",
" \n",
"
\n",
"
290327 rows × 29 columns
\n",
"
"
],
"text/plain": [
" id minute result X Y xG \\\n",
"0 14511 12 Saved Shot 0.728 0.501 0.018741 \n",
"1 14512 16 Blocked Shots 0.789 0.336 0.015598 \n",
"2 14513 25 Saved Shot 0.914 0.188 0.064923 \n",
"3 14514 26 Saved Shot 0.920 0.482 0.057788 \n",
"4 14516 33 Missed Shots 0.922 0.590 0.048801 \n",
"... ... ... ... ... ... ... \n",
"290322 395268 72 Goal 0.885 0.500 0.761299 \n",
"290323 395269 78 Saved Shot 0.937 0.434 0.041579 \n",
"290324 395270 80 Saved Shot 0.836 0.493 0.080786 \n",
"290325 395274 91 Saved Shot 0.867 0.276 0.235170 \n",
"290326 395275 92 Missed Shots 0.764 0.673 0.025288 \n",
"\n",
" player home_away player_id situation ... season \\\n",
"0 Wayne Rooney Home 629 Open Play ... 14/15 \n",
"1 Wayne Rooney Home 629 Open Play ... 14/15 \n",
"2 Juan Mata Home 554 Direct Freekick ... 14/15 \n",
"3 Wayne Rooney Home 629 Open Play ... 14/15 \n",
"4 Wayne Rooney Home 629 From Corner ... 14/15 \n",
"... ... ... ... ... ... ... \n",
"290322 Domenico Criscito Away 3065 Penalty ... 20/21 \n",
"290323 Gianluca Scamacca Away 6253 From Corner ... 20/21 \n",
"290324 Mattia Destro Away 1580 Open Play ... 20/21 \n",
"290325 Gianluca Scamacca Away 6253 Open Play ... 20/21 \n",
"290326 Gianluca Scamacca Away 6253 Open Play ... 20/21 \n",
"\n",
" date year month day X_120 Y_80 team_name \\\n",
"0 2014-08-16 2014 8 16 87.360004 40.079999 Manchester United \n",
"1 2014-08-16 2014 8 16 94.680002 26.879999 Manchester United \n",
"2 2014-08-16 2014 8 16 109.680002 15.039999 Manchester United \n",
"3 2014-08-16 2014 8 16 110.400000 38.560001 Manchester United \n",
"4 2014-08-16 2014 8 16 110.639996 47.200000 Manchester United \n",
"... ... ... ... ... ... ... ... \n",
"290322 2020-12-23 2020 12 23 106.200000 40.000000 Spezia \n",
"290323 2020-12-23 2020 12 23 112.439996 34.720001 Spezia \n",
"290324 2020-12-23 2020 12 23 100.319998 39.439999 Spezia \n",
"290325 2020-12-23 2020 12 23 104.039996 22.080000 Spezia \n",
"290326 2020-12-23 2020 12 23 91.680002 53.840002 Spezia \n",
"\n",
" league_name league_country \n",
"0 Premier League England \n",
"1 Premier League England \n",
"2 Premier League England \n",
"3 Premier League England \n",
"4 Premier League England \n",
"... ... ... \n",
"290322 Seria A Italy \n",
"290323 Seria A Italy \n",
"290324 Seria A Italy \n",
"290325 Seria A Italy \n",
"290326 Seria A Italy \n",
"\n",
"[290327 rows x 29 columns]"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.12. Create New Attributes "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Create `full_fixture_date`"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['full_fixture_date'] = df_understat_combined['date'].astype(str) + ': ' + df_understat_combined['home_team'].astype(str) + ' (' + df_understat_combined['home_goals'].astype(str) + ' ' + ') vs. ' + ' (' + df_understat_combined['away_goals'].astype(str) + ') ' + df_understat_combined['away_team'].astype(str) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Create `player_team` attribute\n",
"Attribute to state the team of the player in the row"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [],
"source": [
"df_understat_combined['player_team'] = np.where(df_understat_combined['home_away'] == 'Home', df_understat_combined['home_team'], df_understat_combined['away_team'])"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" \n",
" id \n",
" minute \n",
" result \n",
" X \n",
" Y \n",
" xG \n",
" player \n",
" home_away \n",
" player_id \n",
" situation \n",
" shot_type \n",
" match_id \n",
" home_team \n",
" away_team \n",
" home_goals \n",
" away_goals \n",
" kick_off \n",
" player_assisted \n",
" last_action \n",
" season \n",
" date \n",
" year \n",
" month \n",
" day \n",
" X_120 \n",
" Y_80 \n",
" team_name \n",
" league_name \n",
" league_country \n",
" full_fixture_date \n",
" player_team \n",
" \n",
" \n",
" \n",
" \n",
" 0 \n",
" 14511 \n",
" 12 \n",
" Saved Shot \n",
" 0.728 \n",
" 0.501 \n",
" 0.018741 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" Open Play \n",
" RightFoot \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16 12:45:00 \n",
" Darren Fletcher \n",
" Pass \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 87.360004 \n",
" 40.079999 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" 2014-08-16: Manchester United (1 ) vs. (2) Sw... \n",
" Manchester United \n",
" \n",
" \n",
" 1 \n",
" 14512 \n",
" 16 \n",
" Blocked Shots \n",
" 0.789 \n",
" 0.336 \n",
" 0.015598 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" Open Play \n",
" RightFoot \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16 12:45:00 \n",
" Chicharito \n",
" Take On \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 94.680002 \n",
" 26.879999 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" 2014-08-16: Manchester United (1 ) vs. (2) Sw... \n",
" Manchester United \n",
" \n",
" \n",
" 2 \n",
" 14513 \n",
" 25 \n",
" Saved Shot \n",
" 0.914 \n",
" 0.188 \n",
" 0.064923 \n",
" Juan Mata \n",
" Home \n",
" 554 \n",
" Direct Freekick \n",
" LeftFoot \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16 12:45:00 \n",
" NaN \n",
" Standard \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 109.680002 \n",
" 15.039999 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" 2014-08-16: Manchester United (1 ) vs. (2) Sw... \n",
" Manchester United \n",
" \n",
" \n",
" 3 \n",
" 14514 \n",
" 26 \n",
" Saved Shot \n",
" 0.920 \n",
" 0.482 \n",
" 0.057788 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" Open Play \n",
" Head \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16 12:45:00 \n",
" Ashley Young \n",
" Aerial \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 110.400000 \n",
" 38.560001 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" 2014-08-16: Manchester United (1 ) vs. (2) Sw... \n",
" Manchester United \n",
" \n",
" \n",
" 4 \n",
" 14516 \n",
" 33 \n",
" Missed Shots \n",
" 0.922 \n",
" 0.590 \n",
" 0.048801 \n",
" Wayne Rooney \n",
" Home \n",
" 629 \n",
" From Corner \n",
" Head \n",
" 4749 \n",
" Manchester United \n",
" Swansea \n",
" 1 \n",
" 2 \n",
" 2014-08-16 12:45:00 \n",
" Juan Mata \n",
" Cross \n",
" 14/15 \n",
" 2014-08-16 \n",
" 2014 \n",
" 8 \n",
" 16 \n",
" 110.639996 \n",
" 47.200000 \n",
" Manchester United \n",
" Premier League \n",
" England \n",
" 2014-08-16: Manchester United (1 ) vs. (2) Sw... \n",
" Manchester United \n",
" \n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id minute result X Y xG player \\\n",
"0 14511 12 Saved Shot 0.728 0.501 0.018741 Wayne Rooney \n",
"1 14512 16 Blocked Shots 0.789 0.336 0.015598 Wayne Rooney \n",
"2 14513 25 Saved Shot 0.914 0.188 0.064923 Juan Mata \n",
"3 14514 26 Saved Shot 0.920 0.482 0.057788 Wayne Rooney \n",
"4 14516 33 Missed Shots 0.922 0.590 0.048801 Wayne Rooney \n",
"\n",
" home_away player_id situation shot_type match_id \\\n",
"0 Home 629 Open Play RightFoot 4749 \n",
"1 Home 629 Open Play RightFoot 4749 \n",
"2 Home 554 Direct Freekick LeftFoot 4749 \n",
"3 Home 629 Open Play Head 4749 \n",
"4 Home 629 From Corner Head 4749 \n",
"\n",
" home_team away_team home_goals away_goals kick_off \\\n",
"0 Manchester United Swansea 1 2 2014-08-16 12:45:00 \n",
"1 Manchester United Swansea 1 2 2014-08-16 12:45:00 \n",
"2 Manchester United Swansea 1 2 2014-08-16 12:45:00 \n",
"3 Manchester United Swansea 1 2 2014-08-16 12:45:00 \n",
"4 Manchester United Swansea 1 2 2014-08-16 12:45:00 \n",
"\n",
" player_assisted last_action season date year month day \\\n",
"0 Darren Fletcher Pass 14/15 2014-08-16 2014 8 16 \n",
"1 Chicharito Take On 14/15 2014-08-16 2014 8 16 \n",
"2 NaN Standard 14/15 2014-08-16 2014 8 16 \n",
"3 Ashley Young Aerial 14/15 2014-08-16 2014 8 16 \n",
"4 Juan Mata Cross 14/15 2014-08-16 2014 8 16 \n",
"\n",
" X_120 Y_80 team_name league_name league_country \\\n",
"0 87.360004 40.079999 Manchester United Premier League England \n",
"1 94.680002 26.879999 Manchester United Premier League England \n",
"2 109.680002 15.039999 Manchester United Premier League England \n",
"3 110.400000 38.560001 Manchester United Premier League England \n",
"4 110.639996 47.200000 Manchester United Premier League England \n",
"\n",
" full_fixture_date player_team \n",
"0 2014-08-16: Manchester United (1 ) vs. (2) Sw... Manchester United \n",
"1 2014-08-16: Manchester United (1 ) vs. (2) Sw... Manchester United \n",
"2 2014-08-16: Manchester United (1 ) vs. (2) Sw... Manchester United \n",
"3 2014-08-16: Manchester United (1 ) vs. (2) Sw... Manchester United \n",
"4 2014-08-16: Manchester United (1 ) vs. (2) Sw... Manchester United "
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_understat_combined.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.13. Clean Team Names "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Parma\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.14. Split the DataFrame by Season \n",
"Split the cleaned and organised combined DataFrame by Season."
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"# Split the cleaned and organised combined DataFrame by Season\n",
"df_understat_1415 = df_understat_combined[df_understat_combined['season'] == '14/15']\n",
"df_understat_1516 = df_understat_combined[df_understat_combined['season'] == '15/16']\n",
"df_understat_1617 = df_understat_combined[df_understat_combined['season'] == '16/17']\n",
"df_understat_1718 = df_understat_combined[df_understat_combined['season'] == '17/18']\n",
"df_understat_1819 = df_understat_combined[df_understat_combined['season'] == '18/19']\n",
"df_understat_1920 = df_understat_combined[df_understat_combined['season'] == '19/20']\n",
"df_understat_2021 = df_understat_combined[df_understat_combined['season'] == '20/21']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.15. Exporting the Engineered DataFrame \n",
"Export the engineered [Understat](https://understat.com/) DataFrame as a single combined CSV file and as seperate files for each season."
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [],
"source": [
"# Export the DataFrame\n",
"\n",
"## Save Combined Big 5 DataFrame to latest DataFrame\n",
"df_understat_combined.to_csv(data_dir_understat + '/engineered/combined/' + 'understat_shooting_big5_1415_2021_latest.csv', index=None, header=True)\n",
"\n",
"## Save another copy of the Combined Big 5 DataFrame to the archive folder\n",
"df_understat_combined.to_csv(data_dir_understat + '/engineered/combined/archive/' + f'understat_shooting_big5_1415_2021_last_updated_{today}.csv', index=None, header=True)\n",
"\n",
"## Save Individual Season DataFrames\n",
"df_understat_1415.to_csv(data_dir_understat + '/engineered/1415/' + 'understat_shooting_big5_1415_big5.csv', index=None, header=True)\n",
"df_understat_1516.to_csv(data_dir_understat + '/engineered/1516/' + 'understat_shooting_big5_1516_big5.csv', index=None, header=True)\n",
"df_understat_1617.to_csv(data_dir_understat + '/engineered/1617/' + 'understat_shooting_big5_1617_big5.csv', index=None, header=True)\n",
"df_understat_1718.to_csv(data_dir_understat + '/engineered/1718/' + 'understat_shooting_big5_1718_big5.csv', index=None, header=True)\n",
"df_understat_1819.to_csv(data_dir_understat + '/engineered/1819/' + 'understat_shooting_big5_1819_big5.csv', index=None, header=True)\n",
"df_understat_1920.to_csv(data_dir_understat + '/engineered/1920/' + 'understat_shooting_big5_1920_big5.csv', index=None, header=True)\n",
"df_understat_2021.to_csv(data_dir_understat + '/engineered/2021/archive/' + f'understat_shooting_big5_2021_big5_last_updated_{today}.csv', index=None, header=True)\n",
"df_understat_2021.to_csv(data_dir_understat + '/engineered/2021/' + 'understat_shooting_big5_2021_big5_latest.csv', index=None, header=True)"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [],
"source": [
"## Export a copy to the Export folder (can be overwritten)\n",
"df_understat_combined.to_csv(data_dir + '/export/understat_shooting_big5_latest.csv', index=None, header=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we have created three pandas DataFrames and wrangled the data to meet our needs, we'll next conduct and [Exploratory Data Analysis ](#section5)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Summary \n",
"This notebook engineers scraped [Understat](https://understat.com/) data using [pandas](http://pandas.pydata.org/) for data manipulation through DataFrames.\n",
"\n",
"With this notebook we now have aggregated the shooting data of all players in the 'Big 5' European leagues from the 14/15 season to the latest 20/21 season data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Next Steps \n",
"This data is now ready to be exported and analysed in further Jupyter notebooks or Tableau.\n",
"\n",
"The Data Engineering subfolder in GitHub can be found [here](https://github.com/eddwebster/football_analytics/tree/master/notebooks/B\\)%20Data%20Engineering)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. References \n",
"\n",
"#### Data and Web Scraping\n",
"* [Understat](https://understat.com/) for the data to scrape\n",
"* [Ben Torvaney](https://twitter.com/Torvaney)'s [Understat Scraper in R](https://gist.github.com/Torvaney/42cd82addb3ba2c4f33ec3247e66889c)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"***Visit my website [EddWebster.com](https://www.eddwebster.com) or my [GitHub Repository](https://github.com/eddwebster) for more projects. If you'd like to get in contact, my Twitter handle is [@eddwebster](http://www.twitter.com/eddwebster) and my email is: edd.j.webster@gmail.com.***"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Back to the top](#top)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"oldHeight": 642,
"position": {
"height": "664px",
"left": "1119px",
"right": "20px",
"top": "-7px",
"width": "489px"
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"varInspector_section_display": "block",
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}