{ "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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
01451112SavedShot0.7280.5010.018741Wayne Rooneyh629OpenPlay2014RightFoot4749Manchester UnitedSwansea122014-08-16T12:45:00ZDarren FletcherPass
11451216BlockedShot0.7890.3360.015598Wayne Rooneyh629OpenPlay2014RightFoot4749Manchester UnitedSwansea122014-08-16T12:45:00ZChicharitoTakeOn
21451325SavedShot0.9140.1880.064923Juan Matah554DirectFreekick2014LeftFoot4749Manchester UnitedSwansea122014-08-16T12:45:00ZNaNStandard
31451426SavedShot0.9200.4820.057788Wayne Rooneyh629OpenPlay2014Head4749Manchester UnitedSwansea122014-08-16T12:45:00ZAshley YoungAerial
41451633MissedShots0.9220.5900.048801Wayne Rooneyh629FromCorner2014Head4749Manchester UnitedSwansea122014-08-16T12:45:00ZJuan MataCross
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
45743743864MissedShots0.6930.5210.012393Corentin Tolissoa3603OpenPlay2014RightFoot5884RennesLyon012015-05-23T20:00:00ZClinton N'JiePass
45744744068MissedShots0.8520.2330.021710Clinton N'Jiea960OpenPlay2014RightFoot5884RennesLyon012015-05-23T20:00:00ZCorentin TolissoChipped
45745744277MissedShots0.7130.5720.013678Maxime Gonalonsa3274OpenPlay2014RightFoot5884RennesLyon012015-05-23T20:00:00ZGueida FofanaPass
45746744385SavedShot0.7610.6490.020611Yassine Benziaa3366OpenPlay2014RightFoot5884RennesLyon012015-05-23T20:00:00ZGueida FofanaPass
45747744485Goal0.9170.4520.594141Clinton N'Jiea960OpenPlay2014RightFoot5884RennesLyon012015-05-23T20:00:00ZMaxime GonalonsTakeOn
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
020024727BlockedShot0.7940.4210.104347Juan Matah554DirectFreekick2015LeftFoot81Manchester UnitedTottenham102015-08-08T15:45:00ZNaNStandard
120024827BlockedShot0.8600.6270.064342Memphis Depayh555SetPiece2015RightFoot81Manchester UnitedTottenham102015-08-08T15:45:00ZAshley YoungPass
220024935BlockedShot0.8430.3330.057157Juan Matah554OpenPlay2015LeftFoot81Manchester UnitedTottenham102015-08-08T15:45:00ZWayne RooneyPass
320025035MissedShots0.8480.5330.092141Juan Matah554OpenPlay2015LeftFoot81Manchester UnitedTottenham102015-08-08T15:45:00ZNaNTackle
420025140BlockedShot0.8120.7070.035742Memphis Depayh555OpenPlay2015RightFoot81Manchester UnitedTottenham102015-08-08T15:45:00ZMichael CarrickBallRecovery
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
454686849460MissedShots0.7950.7230.023267François Moubandjea3205OpenPlay2015RightFoot2248AngersToulouse232016-05-14T23:00:00ZMarcel TisserandPass
454696849664MissedShots0.8830.3470.046925Óscar Trejoa3208SetPiece2015LeftFoot2248AngersToulouse232016-05-14T23:00:00ZAdrien RegattinPass
454706849774SavedShot0.9020.3130.055296Wissam Ben Yeddera3210OpenPlay2015RightFoot2248AngersToulouse232016-05-14T23:00:00ZJean-Armel Kana-BiyikHeadPass
454716849977Goal0.9320.4780.109640Martin Braithwaitea3211OpenPlay2015RightFoot2248AngersToulouse232016-05-14T23:00:00ZPavle NinkovCross
454726850079Goal0.8740.1970.063145Yann Bodigera3206DirectFreekick2015LeftFoot2248AngersToulouse232016-05-14T23:00:00ZNaNStandard
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
01122365MissedShots0.9160.5850.016872Curtis Daviesh1686FromCorner2016Head461HullLeicester212016-08-13T15:30:00ZRobert SnodgrassAerial
111224229MissedShots0.7580.1880.031149Robert Snodgrassh1691DirectFreekick2016LeftFoot461HullLeicester212016-08-13T15:30:00ZNaNStandard
211224333MissedShots0.8390.3240.039379Abel Hernándezh1698OpenPlay2016LeftFoot461HullLeicester212016-08-13T15:30:00ZNaNNone
311224741MissedShots0.7480.3240.015570Robert Snodgrassh1691OpenPlay2016LeftFoot461HullLeicester212016-08-13T15:30:00ZAdama DiomandePass
411224945SavedShot0.9230.6060.033541Curtis Daviesh1686FromCorner2016Head461HullLeicester212016-08-13T15:30:00ZRobert SnodgrassCross
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
4587311062870MissedShots0.8940.6050.031307Mevlüt Erdinca104OpenPlay2016Head4294GuingampMetz102017-05-20T20:00:00ZMatthieu UdolCross
4587411063075BlockedShot0.8720.4790.098524Mevlüt Erdinca104OpenPlay2016LeftFoot4294GuingampMetz102017-05-20T20:00:00ZOpa NguettePass
4587511063279MissedShots0.9010.1350.018259Mevlüt Erdinca104OpenPlay2016RightFoot4294GuingampMetz102017-05-20T20:00:00ZRenaud CohadePass
4587611063485MissedShots0.9830.5690.088932Cheick Doukourea4741SetPiece2016RightFoot4294GuingampMetz102017-05-20T20:00:00ZNaNNone
4587711063588MissedShots0.7210.5780.012905Florent Molleta5677OpenPlay2016RightFoot4294GuingampMetz102017-05-20T20:00:00ZNaNNone
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
01581331Goal0.8850.5260.043622Alexandre Lacazetteh3277OpenPlay2017Head7119ArsenalLeicester432017-08-11T19:45:00ZMohamed ElnenyChipped
11581367MissedShots0.8070.7200.017942Alex Oxlade-Chamberlainh966OpenPlay2017LeftFoot7119ArsenalLeicester432017-08-11T19:45:00ZMesut ÖzilTakeOn
215813713SavedShot0.7860.6430.028923Alex Oxlade-Chamberlainh966OpenPlay2017RightFoot7119ArsenalLeicester432017-08-11T19:45:00ZMesut ÖzilDispossessed
315813821BlockedShot0.9060.6050.375224Danny Welbeckh501OpenPlay2017LeftFoot7119ArsenalLeicester432017-08-11T19:45:00ZMesut ÖzilPass
415813921MissedShots0.6760.5730.010858Granit Xhakah204OpenPlay2017LeftFoot7119ArsenalLeicester432017-08-11T19:45:00ZMohamed ElnenyPass
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
4537321620348BlockedShot0.9730.6990.070225Francois Kamanoa3333OpenPlay2017LeftFoot8944MetzBordeaux042018-05-19T19:00:00ZNaNBallRecovery
4537421620452BlockedShot0.7450.2860.041425Malcoma3262DirectFreekick2017LeftFoot8944MetzBordeaux042018-05-19T19:00:00ZNaNStandard
4537521620559BlockedShot0.8670.4040.120161Younousse Sankharea3474OpenPlay2017LeftFoot8944MetzBordeaux042018-05-19T19:00:00ZYoussouf SabalyPass
4537621621076Goal0.8700.8570.028518Nicolas de Previllea3244OpenPlay2017LeftFoot8944MetzBordeaux042018-05-19T19:00:00ZMaxime PoundjePass
4537721621184MissedShots0.7330.4510.040653Soualiho Meitéa3739OpenPlay2017LeftFoot8944MetzBordeaux042018-05-19T19:00:00ZJaroslav PlasilTakeOn
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
02328111BlockedShot0.8630.7110.039962Alexis Sánchezh498OpenPlay2018RightFoot9197Manchester UnitedLeicester212018-08-10T22:00:00ZLuke ShawPass
12328122Goal0.8850.5000.761169Paul Pogbah1740Penalty2018RightFoot9197Manchester UnitedLeicester212018-08-10T22:00:00ZNaNStandard
223281839SavedShot0.7240.6550.018396Paul Pogbah1740OpenPlay2018RightFoot9197Manchester UnitedLeicester212018-08-10T22:00:00ZAlexis SánchezPass
323281940SavedShot0.8800.6530.081215Luke Shawh1006OpenPlay2018RightFoot9197Manchester UnitedLeicester212018-08-10T22:00:00ZJuan MataChipped
423282155SavedShot0.7810.3300.028309Matteo Darmianh557OpenPlay2018RightFoot9197Manchester UnitedLeicester212018-08-10T22:00:00ZAlexis SánchezPass
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
4719630367166MissedShots0.8970.5330.330207Jonathan Bambaa3749OpenPlay2018RightFoot11022RennesLille312019-05-24T19:05:00ZReinildoCross
4719730367267SavedShot0.9250.6990.051046Jonathan Bambaa3749OpenPlay2018RightFoot11022RennesLille312019-05-24T19:05:00ZLoïc RemyPass
4719830367475MissedShots0.7310.4630.014794Nicolas Pepea5656OpenPlay2018LeftFoot11022RennesLille312019-05-24T19:05:00ZThiago MendesPass
4719930367792BlockedShot0.8960.6400.074316Jonathan Bambaa3749OpenPlay2018RightFoot11022RennesLille312019-05-24T19:05:00ZJonathan IkonePass
4720030367892SavedShot0.9190.5090.103722Gabriela5613FromCorner2018Head11022RennesLille312019-05-24T19:05:00ZNicolas PepeCross
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
030989715MissedShots0.8830.7130.053779Andrew Robertsonh1688OpenPlay2019LeftFoot11643LiverpoolNorwich412019-08-09T20:00:00ZDivock OrigiPass
130989818Goal0.9330.3670.366817Mohamed Salahh1250OpenPlay2019LeftFoot11643LiverpoolNorwich412019-08-09T20:00:00ZRoberto FirminoPass
230990127Goal0.9220.5110.105316Virgil van Dijkh833FromCorner2019Head11643LiverpoolNorwich412019-08-09T20:00:00ZMohamed SalahCross
330990230SavedShot0.8780.5550.112044Roberto Firminoh482OpenPlay2019LeftFoot11643LiverpoolNorwich412019-08-09T20:00:00ZTrent Alexander-ArnoldCross
430990441Goal0.8910.5300.258252Divock Origih484OpenPlay2019Head11643LiverpoolNorwich412019-08-09T20:00:00ZTrent Alexander-ArnoldChipped
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
4388436242945BlockedShot0.8120.6230.042823Houssem Aouara5733OpenPlay2019LeftFoot12982LilleLyon102020-03-08T19:00:00ZBruno GuimarãesPass
4388536243048BlockedShot0.9130.4250.088323Moussa Dembelea7142OpenPlay2019LeftFoot12982LilleLyon102020-03-08T19:00:00ZKarl Toko EkambiCross
4388636243460MissedShots0.8440.5690.057904Bruno Guimarãesa8327SetPiece2019RightFoot12982LilleLyon102020-03-08T19:00:00ZNaNNone
4388736243591MissedShots0.8980.3770.255291Bertrand Traoréa695OpenPlay2019LeftFoot12982LilleLyon102020-03-08T19:00:00ZMartin TerrierTakeOn
4388836243794MissedShots0.7340.5910.016734Bruno Guimarãesa8327OpenPlay2019RightFoot12982LilleLyon102020-03-08T19:00:00ZKarl Toko EkambiPass
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
03764776SavedShot0.7850.2490.020528Denis Odoih7077OpenPlay2020LeftFoot14086FulhamArsenal032020-09-12T11:30:00ZIvan CavaleiroPass
13764819BlockedShot0.9330.3420.045429Neeskens Kebanoh6840OpenPlay2020RightFoot14086FulhamArsenal032020-09-12T11:30:00ZIvan CavaleiroCross
237648755MissedShots0.8130.3190.020672Aboubakar Kamarah4866SetPiece2020RightFoot14086FulhamArsenal032020-09-12T11:30:00ZNaNNone
337649066SavedShot0.8030.6550.034215Aleksandar Mitrovich773OpenPlay2020RightFoot14086FulhamArsenal032020-09-12T11:30:00ZFranck ZamboPass
437649489MissedShots0.5960.2920.005483Bobby Reidh6827OpenPlay2020RightFoot14086FulhamArsenal032020-09-12T11:30:00ZNaNNone
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerh_aplayer_idsituationseasonshotTypematch_idh_teama_teamh_goalsa_goalsdateplayer_assistedlastAction
1675539552545SavedShot0.7920.2730.016651Kenny Lalaa5975OpenPlay2020RightFoot15924Paris Saint GermainStrasbourg402020-12-23T20:00:00ZNaNNone
1675639552755BlockedShot0.8030.6450.028917Lionel Carolea6318OpenPlay2020LeftFoot15924Paris Saint GermainStrasbourg402020-12-23T20:00:00ZJean-Ricner BellegardePass
1675739552965MissedShots0.9350.4850.088725Mohamed Simakana7551FromCorner2020RightFoot15924Paris Saint GermainStrasbourg402020-12-23T20:00:00ZNaNAerial
1675839553274MissedShots0.7930.6490.025098Sanjin Prcica1932OpenPlay2020RightFoot15924Paris Saint GermainStrasbourg402020-12-23T20:00:00ZNaNBallRecovery
1675939553485BlockedShot0.6980.3120.008228Kenny Lalaa5975OpenPlay2020RightFoot15924Paris Saint GermainStrasbourg402020-12-23T20:00:00ZJean Eudes AholouPass
\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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idminuteXYxGplayer_idseasonmatch_idh_goalsa_goals
count16760.00000016760.00000016760.00000016760.00000016760.00000016760.00000016760.016760.00000016760.00000016760.000000
mean385974.26330548.5551310.8481980.5073760.1183754339.0294152020.014987.3739861.5446901.453998
std5697.37641426.6535200.0924920.1257840.1714062898.6849720.0611.3609561.3540881.192357
min375453.0000000.0000000.0040000.0000000.0000003.0000002020.013977.0000000.0000000.000000
25%381067.75000026.0000000.7890000.4190000.0258111491.7500002020.014491.0000001.0000001.000000
50%385991.50000049.0000000.8680000.5030000.0535714234.0000002020.014916.0000001.0000001.000000
75%390978.25000071.0000000.9110000.5980000.1001117006.0000002020.015508.0000002.0000002.000000
max395596.000000100.0000000.9970000.9950000.9782889205.0000002020.015925.0000008.0000007.000000
\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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerhome_awayplayer_idsituation...kick_offplayer_assistedlast_actionseasondateyearmonthdayX_120Y_80
01451112Saved Shot0.7280.5010.018741Wayne RooneyHome629OpenPlay...2014-08-16 12:45:00Darren FletcherPass14/152014-08-16201481687.36000440.079999
11451216Blocked Shots0.7890.3360.015598Wayne RooneyHome629OpenPlay...2014-08-16 12:45:00ChicharitoTakeOn14/152014-08-16201481694.68000226.879999
21451325Saved Shot0.9140.1880.064923Juan MataHome554DirectFreekick...2014-08-16 12:45:00NaNStandard14/152014-08-162014816109.68000215.039999
31451426Saved Shot0.9200.4820.057788Wayne RooneyHome629OpenPlay...2014-08-16 12:45:00Ashley YoungAerial14/152014-08-162014816110.40000038.560001
41451633Missed Shots0.9220.5900.048801Wayne RooneyHome629FromCorner...2014-08-16 12:45:00Juan MataCross14/152014-08-162014816110.63999647.200000
\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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
team_nameleague_nameleague_country
0AC MilanSeria AItaly
1AlavesLa LigaSpain
2AlmeriaLa LigaSpain
3AmiensLigue 1France
4AngersLigue 1France
\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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerhome_awayplayer_idsituation...seasondateyearmonthdayX_120Y_80team_nameleague_nameleague_country
01451112Saved Shot0.7280.5010.018741Wayne RooneyHome629Open Play...14/152014-08-16201481687.36000440.079999Manchester UnitedPremier LeagueEngland
11451216Blocked Shots0.7890.3360.015598Wayne RooneyHome629Open Play...14/152014-08-16201481694.68000226.879999Manchester UnitedPremier LeagueEngland
21451325Saved Shot0.9140.1880.064923Juan MataHome554Direct Freekick...14/152014-08-162014816109.68000215.039999Manchester UnitedPremier LeagueEngland
31451426Saved Shot0.9200.4820.057788Wayne RooneyHome629Open Play...14/152014-08-162014816110.40000038.560001Manchester UnitedPremier LeagueEngland
41451633Missed Shots0.9220.5900.048801Wayne RooneyHome629From Corner...14/152014-08-162014816110.63999647.200000Manchester UnitedPremier LeagueEngland
..................................................................
29032239526872Goal0.8850.5000.761299Domenico CriscitoAway3065Penalty...20/212020-12-2320201223106.20000040.000000SpeziaSeria AItaly
29032339526978Saved Shot0.9370.4340.041579Gianluca ScamaccaAway6253From Corner...20/212020-12-2320201223112.43999634.720001SpeziaSeria AItaly
29032439527080Saved Shot0.8360.4930.080786Mattia DestroAway1580Open Play...20/212020-12-2320201223100.31999839.439999SpeziaSeria AItaly
29032539527491Saved Shot0.8670.2760.235170Gianluca ScamaccaAway6253Open Play...20/212020-12-2320201223104.03999622.080000SpeziaSeria AItaly
29032639527592Missed Shots0.7640.6730.025288Gianluca ScamaccaAway6253Open Play...20/212020-12-232020122391.68000253.840002SpeziaSeria AItaly
\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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idminuteresultXYxGplayerhome_awayplayer_idsituationshot_typematch_idhome_teamaway_teamhome_goalsaway_goalskick_offplayer_assistedlast_actionseasondateyearmonthdayX_120Y_80team_nameleague_nameleague_countryfull_fixture_dateplayer_team
01451112Saved Shot0.7280.5010.018741Wayne RooneyHome629Open PlayRightFoot4749Manchester UnitedSwansea122014-08-16 12:45:00Darren FletcherPass14/152014-08-16201481687.36000440.079999Manchester UnitedPremier LeagueEngland2014-08-16: Manchester United (1 ) vs. (2) Sw...Manchester United
11451216Blocked Shots0.7890.3360.015598Wayne RooneyHome629Open PlayRightFoot4749Manchester UnitedSwansea122014-08-16 12:45:00ChicharitoTake On14/152014-08-16201481694.68000226.879999Manchester UnitedPremier LeagueEngland2014-08-16: Manchester United (1 ) vs. (2) Sw...Manchester United
21451325Saved Shot0.9140.1880.064923Juan MataHome554Direct FreekickLeftFoot4749Manchester UnitedSwansea122014-08-16 12:45:00NaNStandard14/152014-08-162014816109.68000215.039999Manchester UnitedPremier LeagueEngland2014-08-16: Manchester United (1 ) vs. (2) Sw...Manchester United
31451426Saved Shot0.9200.4820.057788Wayne RooneyHome629Open PlayHead4749Manchester UnitedSwansea122014-08-16 12:45:00Ashley YoungAerial14/152014-08-162014816110.40000038.560001Manchester UnitedPremier LeagueEngland2014-08-16: Manchester United (1 ) vs. (2) Sw...Manchester United
41451633Missed Shots0.9220.5900.048801Wayne RooneyHome629From CornerHead4749Manchester UnitedSwansea122014-08-16 12:45:00Juan MataCross14/152014-08-162014816110.63999647.200000Manchester UnitedPremier LeagueEngland2014-08-16: Manchester United (1 ) vs. (2) Sw...Manchester United
\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 }