# Python ≥3.5 (ideally)
import platform
import sys, getopt
assert sys.version_info >= (3, 5)
import csv
# Import Dependencies
%matplotlib inline
# Math Operations
import numpy as np
from math import pi
# Datetime
import datetime
from datetime import date
import time
# Data Preprocessing
import pandas as pd # version 1.0.3
import os # used to read the csv filenames
import re
import random
from io import BytesIO
from pathlib import Path
# Reading directories
import glob
import os
# Working with JSON
import json
from pandas.io.json import json_normalize
from ast import literal_eval
# Data Visualisation
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('seaborn-whitegrid')
import missingno as msno # visually display missing data
# Display in Jupyter
from IPython.display import Image, YouTubeVideo
from IPython.core.display import HTML
# Ignore Warnings
import warnings
warnings.filterwarnings(action="ignore", message="^internal gelsd")
print('Setup Complete')
Setup Complete
# Set up initial paths to subfolders
base_dir = os.path.join('..', '..', )
data_dir = os.path.join(base_dir, 'data')
data_dir_fbref = os.path.join(base_dir, 'data', 'fbref')
data_dir_tm = os.path.join(base_dir, 'data', 'tm')
data_dir_wyscout = os.path.join(base_dir, 'data', 'wyscout')
img_dir = os.path.join(base_dir, 'img')
fig_dir = os.path.join(base_dir, 'img', 'fig')
video_dir = os.path.join(base_dir, 'video')
# Show files in directory
print(glob.glob(data_dir_wyscout + '/engineered/combined/*.csv'))
['../../data/wyscout/engineered/combined/wyscout_events_big5_1718.csv', '../../data/wyscout/engineered/combined/wyscout_aggregated_team_big5_1718.csv', '../../data/wyscout/engineered/combined/wyscout_aggregated_fixtures_big5_1718.csv']
df_wyscout = pd.read_csv(data_dir_wyscout + '/engineered/combined/wyscout_events_big5_1718.csv')
pd.set_option('display.max_columns', None)
# Display the first 5 rows of the raw DataFrame, df_wyscout
df_wyscout.head()
eventId | subEventName | tags | playerId | positions | matchId | eventName | teamId | matchPeriod | eventSec | subEventId | id | status | roundId | gameweek | seasonId | dateutc | winner | venue | wyId_x | label | date | referees | duration | competitionId | league_name | wyId_y | country | weight | firstName | middleName | lastName | birthDate | height | wyId_x.1 | foot | shortName | passportArea.name | role.name | birthArea.name | fullName | teamName | wyId_y.1 | fixture | score_home_away | team_home | team_away | goals_home | goals_away | date_isolated | time_isolated | date_time_isolated | date_time_timestamp | date_date | time_time | full_fixture_date | season | teamIdNext | teamNameNext | fullNameNext | player2player | isPossessionRetained | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 8 | Simple pass | [{'id': 1801}] | 134351 | [{'y': 50, 'x': 50}, {'y': 57, 'x': 40}] | 2499930 | Pass | 1659 | 1H | 1.914449 | 85.0 | 218431699 | Played | 4405654 | 22 | 181150 | 2018-01-01 12:30:00 | 0 | The American Express Community Stadium | 2499930 | Brighton & Hove Albion - AFC Bournemouth, 2 - 2 | January 1, 2018 at 1:30:00 PM GMT+1 | [{'refereeId': 384965, 'role': 'referee'}, {'r... | Regular | 364 | Premier League | 364 | England | 78 | Benik | NaN | Afobe | 1993-02-12 | 183 | 134351 | right | B. Afobe | Congo DR | Forward | England | Benik Afobe | AFC Bournemouth | 1659 | Brighton & Hove Albion - AFC Bournemouth | 2 - 2 | Brighton & Hove Albion | AFC Bournemouth | 2 | 2 | January 1, 2018 | 1:30:00 PM GMT+1 | January 1, 2018 1:30:00 PM | 2018-01-01 13:30:00 | 01-01-2018 | 13:30:00 | 01-01-2018 Brighton & Hove Albion 2 v 2 AFC ... | 17/18 | 1659.0 | AFC Bournemouth | Lewis Cook | Benik Afobe - Lewis Cook | True |
1 | 8 | Simple pass | [{'id': 1801}] | 302518 | [{'y': 57, 'x': 40}, {'y': 12, 'x': 33}] | 2499930 | Pass | 1659 | 1H | 2.784230 | 85.0 | 218431700 | Played | 4405654 | 22 | 181150 | 2018-01-01 12:30:00 | 0 | The American Express Community Stadium | 2499930 | Brighton & Hove Albion - AFC Bournemouth, 2 - 2 | January 1, 2018 at 1:30:00 PM GMT+1 | [{'refereeId': 384965, 'role': 'referee'}, {'r... | Regular | 364 | Premier League | 364 | England | 71 | Lewis | NaN | Cook | 1997-02-03 | 175 | 302518 | right | L. Cook | England | Midfielder | England | Lewis Cook | AFC Bournemouth | 1659 | Brighton & Hove Albion - AFC Bournemouth | 2 - 2 | Brighton & Hove Albion | AFC Bournemouth | 2 | 2 | January 1, 2018 | 1:30:00 PM GMT+1 | January 1, 2018 1:30:00 PM | 2018-01-01 13:30:00 | 01-01-2018 | 13:30:00 | 01-01-2018 Brighton & Hove Albion 2 v 2 AFC ... | 17/18 | 1659.0 | AFC Bournemouth | Charlie Daniels | Lewis Cook - Charlie Daniels | True |
2 | 8 | Simple pass | [{'id': 1801}] | 9285 | [{'y': 12, 'x': 33}, {'y': 4, 'x': 38}] | 2499930 | Pass | 1659 | 1H | 5.040106 | 85.0 | 218431701 | Played | 4405654 | 22 | 181150 | 2018-01-01 12:30:00 | 0 | The American Express Community Stadium | 2499930 | Brighton & Hove Albion - AFC Bournemouth, 2 - 2 | January 1, 2018 at 1:30:00 PM GMT+1 | [{'refereeId': 384965, 'role': 'referee'}, {'r... | Regular | 364 | Premier League | 364 | England | 75 | Charlie | NaN | Daniels | 1986-09-07 | 178 | 9285 | left | C. Daniels | England | Defender | England | Charlie Daniels | AFC Bournemouth | 1659 | Brighton & Hove Albion - AFC Bournemouth | 2 - 2 | Brighton & Hove Albion | AFC Bournemouth | 2 | 2 | January 1, 2018 | 1:30:00 PM GMT+1 | January 1, 2018 1:30:00 PM | 2018-01-01 13:30:00 | 01-01-2018 | 13:30:00 | 01-01-2018 Brighton & Hove Albion 2 v 2 AFC ... | 17/18 | 1659.0 | AFC Bournemouth | Marc Pugh | Charlie Daniels - Marc Pugh | True |
3 | 8 | Simple pass | [{'id': 1801}] | 9293 | [{'y': 4, 'x': 38}, {'y': 26, 'x': 41}] | 2499930 | Pass | 1659 | 1H | 6.544869 | 85.0 | 218431702 | Played | 4405654 | 22 | 181150 | 2018-01-01 12:30:00 | 0 | The American Express Community Stadium | 2499930 | Brighton & Hove Albion - AFC Bournemouth, 2 - 2 | January 1, 2018 at 1:30:00 PM GMT+1 | [{'refereeId': 384965, 'role': 'referee'}, {'r... | Regular | 364 | Premier League | 364 | England | 72 | Marc | NaN | Pugh | 1987-04-02 | 180 | 9293 | right | M. Pugh | England | Midfielder | England | Marc Pugh | AFC Bournemouth | 1659 | Brighton & Hove Albion - AFC Bournemouth | 2 - 2 | Brighton & Hove Albion | AFC Bournemouth | 2 | 2 | January 1, 2018 | 1:30:00 PM GMT+1 | January 1, 2018 1:30:00 PM | 2018-01-01 13:30:00 | 01-01-2018 | 13:30:00 | 01-01-2018 Brighton & Hove Albion 2 v 2 AFC ... | 17/18 | 1659.0 | AFC Bournemouth | Harry Arter | Marc Pugh - Harry Arter | True |
4 | 8 | Simple pass | [{'id': 1801}] | 9283 | [{'y': 26, 'x': 41}, {'y': 10, 'x': 53}] | 2499930 | Pass | 1659 | 1H | 8.245745 | 85.0 | 218431703 | Played | 4405654 | 22 | 181150 | 2018-01-01 12:30:00 | 0 | The American Express Community Stadium | 2499930 | Brighton & Hove Albion - AFC Bournemouth, 2 - 2 | January 1, 2018 at 1:30:00 PM GMT+1 | [{'refereeId': 384965, 'role': 'referee'}, {'r... | Regular | 364 | Premier League | 364 | England | 70 | Harry | NaN | Arter | 1989-12-28 | 178 | 9283 | right | H. Arter | Ireland Republic | Midfielder | England | Harry Arter | AFC Bournemouth | 1659 | Brighton & Hove Albion - AFC Bournemouth | 2 - 2 | Brighton & Hove Albion | AFC Bournemouth | 2 | 2 | January 1, 2018 | 1:30:00 PM GMT+1 | January 1, 2018 1:30:00 PM | 2018-01-01 13:30:00 | 01-01-2018 | 13:30:00 | 01-01-2018 Brighton & Hove Albion 2 v 2 AFC ... | 17/18 | 1659.0 | AFC Bournemouth | Marc Pugh | Harry Arter - Marc Pugh | True |
# Print the shape of the raw DataFrame, ddf_wyscout_raw
print(df_wyscout.shape)
(2845357, 62)
# Display all column names
list(df_wyscout.columns)
['eventId', 'subEventName', 'tags', 'playerId', 'positions', 'matchId', 'eventName', 'teamId', 'matchPeriod', 'eventSec', 'subEventId', 'id', 'status', 'roundId', 'gameweek', 'seasonId', 'dateutc', 'winner', 'venue', 'wyId_x', 'label', 'date', 'referees', 'duration', 'competitionId', 'league_name', 'wyId_y', 'country', 'weight', 'firstName', 'middleName', 'lastName', 'birthDate', 'height', 'wyId_x.1', 'foot', 'shortName', 'passportArea.name', 'role.name', 'birthArea.name', 'fullName', 'teamName', 'wyId_y.1', 'fixture', 'score_home_away', 'team_home', 'team_away', 'goals_home', 'goals_away', 'date_isolated', 'time_isolated', 'date_time_isolated', 'date_time_timestamp', 'date_date', 'time_time', 'full_fixture_date', 'season', 'teamIdNext', 'teamNameNext', 'fullNameNext', 'player2player', 'isPossessionRetained']
# Data types of the features of the raw DataFrame, df_raw
with pd.option_context('display.max_rows', None, 'display.max_columns', None):
print(df_wyscout.dtypes)
eventId int64 subEventName object tags object playerId int64 positions object matchId int64 eventName object teamId int64 matchPeriod object eventSec float64 subEventId float64 id int64 status object roundId int64 gameweek int64 seasonId int64 dateutc object winner int64 venue object wyId_x int64 label object date object referees object duration object competitionId int64 league_name object wyId_y int64 country object weight int64 firstName object middleName float64 lastName object birthDate object height int64 wyId_x.1 int64 foot object shortName object passportArea.name object role.name object birthArea.name object fullName object teamName object wyId_y.1 int64 fixture object score_home_away object team_home object team_away object goals_home int64 goals_away int64 date_isolated object time_isolated object date_time_isolated object date_time_timestamp object date_date object time_time object full_fixture_date object season object teamIdNext float64 teamNameNext object fullNameNext object player2player object isPossessionRetained bool dtype: object
# Select columns of interest
## Define columns
cols = ['date_time_timestamp',
'league_name',
'fixture',
'team_home',
'team_away',
'teamName',
'goals_home',
'goals_away',
'eventName',
'subEventName'
]
##
df_wyscout_select = df_wyscout[cols]
##
df_wyscout_select['Opponent'] = np.where(df_wyscout_select['team_home'] == df_wyscout_select['teamName'], df_wyscout_select['team_away'], df_wyscout_select['team_home'])
/opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:20: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
#
##
df_wyscout_fixture_grouped = (df_wyscout_select
#.groupby(['full_fixture_date'])
.groupby(['date_time_timestamp',
'league_name',
'fixture',
'teamName',
'Opponent',
'goals_home',
'goals_away',
'eventName',
'subEventName'])
.agg({'eventName': ['count']},
{'subEventName': ['count']}
)
)
##
df_wyscout_fixture_grouped.columns = df_wyscout_fixture_grouped.columns.droplevel(level=0)
##
df_wyscout_fixture_grouped = df_wyscout_fixture_grouped.reset_index()
##
df_wyscout_fixture_grouped = df_wyscout_fixture_grouped.rename(columns={'date_time_timestamp': 'Date',
'league_name': 'League_Name',
'fixture': 'Fixture',
'teamName': 'Team',
'Opponent': 'Opponent',
'goals_home': 'Goals_Home',
'goals_away': 'Goals_Away',
'eventName': 'Event',
'subEventName': 'SubEvent',
'count': 'Team_Value'
}
)
##
df_wyscout_fixture_grouped.head()
Date | League_Name | Fixture | Team | Opponent | Goals_Home | Goals_Away | Event | SubEvent | Team_Value | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | Air duel | 67 |
1 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | Ground attacking duel | 75 |
2 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | Ground defending duel | 49 |
3 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | Ground loose ball duel | 29 |
4 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Foul | Foul | 12 |
# List unique values in the df_wyscout_fixture_grouped['Event_Name'] column
df_wyscout_fixture_grouped.Event.unique()
array(['Duel', 'Foul', 'Free Kick', 'Goalkeeper leaving line', 'Others on the ball', 'Pass', 'Save attempt', 'Shot', 'Interruption'], dtype=object)
# List unique values in the df_wyscout_fixture_grouped['SubEvent_Name'] column
df_wyscout_fixture_grouped.SubEvent.unique()
array(['Air duel', 'Ground attacking duel', 'Ground defending duel', 'Ground loose ball duel', 'Foul', 'Corner', 'Free Kick', 'Free kick cross', 'Free kick shot', 'Goal kick', 'Throw in', 'Goalkeeper leaving line', 'Acceleration', 'Clearance', 'Touch', 'Cross', 'Hand pass', 'Head pass', 'High pass', 'Launch', 'Simple pass', 'Smart pass', 'Reflexes', 'Save attempt', 'Shot', 'Hand foul', 'Penalty', 'Out of game foul', 'Protest', 'Simulation', 'Late card foul', 'Time lost foul', 'Violent Foul', 'Ball out of the field', 'Whistle'], dtype=object)
# Select columns of interest
## Define columns
cols = ['Date',
'League_Name',
'Fixture',
'Team',
'Opponent',
'Event',
'SubEvent_Name',
'Team_Value'
]
##
df_wyscout_fixture_grouped_select = df_wyscout_fixture_grouped[cols]
# Join DataFrame to itself on 'Date', 'Fixture', 'Team'/'Opponent', and 'Event', to join Team and Opponent together
df_wyscout_fixture_grouped = pd.merge(df_wyscout_fixture_grouped, df_wyscout_fixture_grouped, how='left', left_on=['Date', 'League_Name', 'Fixture', 'Opponent', 'Event'], right_on = ['Date', 'League_Name', 'Fixture', 'Team', 'Event'])
df_wyscout_fixture_grouped
Date | League_Name | Fixture | Team_x | Opponent_x | Goals_Home_x | Goals_Away_x | Event | Team_Value_x | Team_y | Opponent_y | Goals_Home_y | Goals_Away_y | Team_Value_y | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | 220 | Toulouse | Monaco | 3.0 | 2.0 | 205.0 |
1 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Foul | 12 | Toulouse | Monaco | 3.0 | 2.0 | 23.0 |
2 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Free Kick | 58 | Toulouse | Monaco | 3.0 | 2.0 | 47.0 |
3 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Goalkeeper leaving line | 2 | NaN | NaN | NaN | NaN | NaN |
4 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Offside | 5 | Toulouse | Monaco | 3.0 | 2.0 | 1.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
24763 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Offside | 3 | Barcelona | Real Sociedad | 1.0 | 0.0 | 3.0 |
24764 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Others on the ball | 81 | Barcelona | Real Sociedad | 1.0 | 0.0 | 95.0 |
24765 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Pass | 360 | Barcelona | Real Sociedad | 1.0 | 0.0 | 592.0 |
24766 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Save attempt | 4 | Barcelona | Real Sociedad | 1.0 | 0.0 | 2.0 |
24767 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Shot | 12 | Barcelona | Real Sociedad | 1.0 | 0.0 | 10.0 |
24768 rows × 14 columns
# Clean Data
## Drop columns
df_wyscout_fixture_grouped = df_wyscout_fixture_grouped.drop(columns=['Team_y', 'Opponent_y', 'Goals_Home_y', 'Goals_Away_y'])
## Rename columns
df_wyscout_fixture_grouped = df_wyscout_fixture_grouped.rename(columns={'Team_x': 'Team',
'Opponent_x': 'Opponent',
'Goals_Home_x': 'Goals_Home',
'Goals_Away_x': 'Goals_Away',
'Team_Value_x': 'Team_Value',
'Team_Value_y': 'Opponent_Value',
}
)
## Replace null values with zeros
df_wyscout_fixture_grouped['Team_Value'] = df_wyscout_fixture_grouped['Team_Value'].replace(np.nan, 0)
df_wyscout_fixture_grouped['Opponent_Value'] = df_wyscout_fixture_grouped['Opponent_Value'].replace(np.nan, 0)
## Convert Opponent_Value' from Float64 to Int64 type
df_wyscout_fixture_grouped['Opponent_Value'] = df_wyscout_fixture_grouped['Opponent_Value'].astype('Int64')
## Display DataFrame
df_wyscout_fixture_grouped.head()
Date | League_Name | Fixture | Team | Opponent | Goals_Home | Goals_Away | Event | Team_Value | Opponent_Value | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | 220 | 205 |
1 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Foul | 12 | 23 |
2 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Free Kick | 58 | 47 |
3 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Goalkeeper leaving line | 2 | 0 |
4 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Offside | 5 | 1 |
#
##
df_fixture_gw = (df_wyscout_fixture_grouped
.groupby(['Date', 'Team'])
.agg({'Team': ['nunique']})
)
##
df_fixture_gw.columns = df_fixture_gw.columns.droplevel(level=0)
##
df_fixture_gw = df_fixture_gw.reset_index()
##
df_fixture_gw = df_fixture_gw.rename(columns={'Date': 'Date',
'nunique': 'Gameweek',
}
)
## Groupby. See: https://stackoverflow.com/questions/18554920/pandas-aggregate-count-distinct
df_fixture_gw = (df_fixture_gw.groupby(['Team', 'Date']).sum()
.groupby(level=0).cumsum().reset_index()
)
## Display DataFrame
df_fixture_gw.head()
Team | Date | Gameweek | |
---|---|---|---|
0 | AFC Bournemouth | 2017-08-12 16:00:00 | 1 |
1 | AFC Bournemouth | 2017-08-19 16:00:00 | 2 |
2 | AFC Bournemouth | 2017-08-26 13:30:00 | 3 |
3 | AFC Bournemouth | 2017-09-09 16:00:00 | 4 |
4 | AFC Bournemouth | 2017-09-15 21:00:00 | 5 |
# Join DataFrame
df_wyscout_fixture_grouped = pd.merge(df_wyscout_fixture_grouped, df_fixture_gw, how='left', left_on=['Date', 'Team'], right_on = ['Date', 'Team'])
# Display DataFrame
df_wyscout_fixture_grouped.head(50)
Date | League_Name | Fixture | Team | Opponent | Goals_Home | Goals_Away | Event | Team_Value | Opponent_Value | Gameweek | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Duel | 220 | 205 | 1 |
1 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Foul | 12 | 23 | 1 |
2 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Free Kick | 58 | 47 | 1 |
3 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Goalkeeper leaving line | 2 | 0 | 1 |
4 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Offside | 5 | 1 | 1 |
5 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Others on the ball | 46 | 49 | 1 |
6 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Pass | 467 | 170 | 1 |
7 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Save attempt | 4 | 7 | 1 |
8 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Monaco | Toulouse | 3 | 2 | Shot | 12 | 4 | 1 |
9 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Duel | 205 | 220 | 1 |
10 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Foul | 23 | 12 | 1 |
11 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Free Kick | 47 | 58 | 1 |
12 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Offside | 1 | 5 | 1 |
13 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Others on the ball | 49 | 46 | 1 |
14 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Pass | 170 | 467 | 1 |
15 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Save attempt | 7 | 4 | 1 |
16 | 2017-08-04 20:45:00 | Ligue 1 | Monaco - Toulouse | Toulouse | Monaco | 3 | 2 | Shot | 4 | 12 | 1 |
17 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Duel | 205 | 192 | 1 |
18 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Foul | 12 | 9 | 1 |
19 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Free Kick | 33 | 41 | 1 |
20 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Goalkeeper leaving line | 1 | 3 | 1 |
21 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Others on the ball | 82 | 55 | 1 |
22 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Pass | 328 | 724 | 1 |
23 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Save attempt | 5 | 1 | 1 |
24 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | Amiens SC | PSG | 2 | 0 | Shot | 6 | 15 | 1 |
25 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Duel | 192 | 205 | 1 |
26 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Foul | 9 | 12 | 1 |
27 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Free Kick | 41 | 33 | 1 |
28 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Goalkeeper leaving line | 3 | 1 | 1 |
29 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Offside | 3 | 0 | 1 |
30 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Others on the ball | 55 | 82 | 1 |
31 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Pass | 724 | 328 | 1 |
32 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Save attempt | 1 | 5 | 1 |
33 | 2017-08-05 17:15:00 | Ligue 1 | PSG - Amiens SC | PSG | Amiens SC | 2 | 0 | Shot | 15 | 6 | 1 |
34 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Duel | 160 | 168 | 1 |
35 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Foul | 12 | 7 | 1 |
36 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Free Kick | 34 | 51 | 1 |
37 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Goalkeeper leaving line | 4 | 1 | 1 |
38 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Offside | 1 | 3 | 1 |
39 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Others on the ball | 46 | 44 | 1 |
40 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Pass | 396 | 528 | 1 |
41 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Save attempt | 4 | 5 | 1 |
42 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Guingamp | Metz | 1 | 3 | Shot | 8 | 6 | 1 |
43 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Duel | 168 | 160 | 1 |
44 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Foul | 7 | 12 | 1 |
45 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Free Kick | 51 | 34 | 1 |
46 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Goalkeeper leaving line | 1 | 4 | 1 |
47 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Offside | 3 | 1 | 1 |
48 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Others on the ball | 44 | 46 | 1 |
49 | 2017-08-05 20:00:00 | Ligue 1 | Metz - Guingamp | Metz | Guingamp | 1 | 3 | Pass | 528 | 396 | 1 |
## Display DataFrame
df_wyscout_fixture_grouped.tail(50)
Date | League_Name | Fixture | Team | Opponent | Goals_Home | Goals_Away | Event | Team_Value | Opponent_Value | Gameweek | |
---|---|---|---|---|---|---|---|---|---|---|---|
24718 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Free Kick | 36 | 39 | 38 |
24719 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Goalkeeper leaving line | 3 | 2 | 38 |
24720 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Offside | 2 | 5 | 38 |
24721 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Others on the ball | 67 | 78 | 38 |
24722 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Pass | 512 | 407 | 38 |
24723 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Save attempt | 4 | 3 | 38 |
24724 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Athletic Club | Espanyol | 0 | 1 | Shot | 9 | 12 | 38 |
24725 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Duel | 147 | 154 | 38 |
24726 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Foul | 11 | 4 | 38 |
24727 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Free Kick | 39 | 36 | 38 |
24728 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Goalkeeper leaving line | 2 | 3 | 38 |
24729 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Offside | 5 | 2 | 38 |
24730 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Others on the ball | 78 | 67 | 38 |
24731 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Pass | 407 | 512 | 38 |
24732 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Save attempt | 3 | 4 | 38 |
24733 | 2018-05-20 16:15:00 | La Liga | Athletic Club - Espanyol | Espanyol | Athletic Club | 0 | 1 | Shot | 12 | 9 | 38 |
24734 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Duel | 191 | 181 | 38 |
24735 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Foul | 15 | 13 | 38 |
24736 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Free Kick | 56 | 34 | 38 |
24737 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Offside | 6 | 0 | 38 |
24738 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Others on the ball | 56 | 64 | 38 |
24739 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Pass | 428 | 406 | 38 |
24740 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Save attempt | 6 | 4 | 38 |
24741 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Atl\u00e9tico Madrid | Eibar | 2 | 2 | Shot | 7 | 16 | 38 |
24742 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Duel | 181 | 191 | 38 |
24743 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Foul | 13 | 15 | 38 |
24744 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Free Kick | 34 | 56 | 38 |
24745 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Goalkeeper leaving line | 2 | 0 | 38 |
24746 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Others on the ball | 64 | 56 | 38 |
24747 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Pass | 406 | 428 | 38 |
24748 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Save attempt | 4 | 6 | 38 |
24749 | 2018-05-20 18:30:00 | La Liga | Atl\u00e9tico Madrid - Eibar | Eibar | Atl\u00e9tico Madrid | 2 | 2 | Shot | 16 | 7 | 38 |
24750 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Duel | 182 | 200 | 38 |
24751 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Foul | 13 | 13 | 38 |
24752 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Free Kick | 38 | 37 | 38 |
24753 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Goalkeeper leaving line | 2 | 1 | 38 |
24754 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Offside | 3 | 3 | 38 |
24755 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Others on the ball | 95 | 81 | 38 |
24756 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Pass | 592 | 360 | 38 |
24757 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Save attempt | 2 | 4 | 38 |
24758 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Barcelona | Real Sociedad | 1 | 0 | Shot | 10 | 12 | 38 |
24759 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Duel | 200 | 182 | 38 |
24760 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Foul | 13 | 13 | 38 |
24761 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Free Kick | 37 | 38 | 38 |
24762 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Goalkeeper leaving line | 1 | 2 | 38 |
24763 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Offside | 3 | 3 | 38 |
24764 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Others on the ball | 81 | 95 | 38 |
24765 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Pass | 360 | 592 | 38 |
24766 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Save attempt | 4 | 2 | 38 |
24767 | 2018-05-20 20:45:00 | La Liga | Barcelona - Real Sociedad | Real Sociedad | Barcelona | 1 | 0 | Shot | 12 | 10 | 38 |
df_wyscout_fixture_grouped.to_csv(data_dir_wyscout + '/engineered/combined/wyscout_aggregated_fixtures_big5_1718.csv', index=None, header=True)
# Group DataFrame by Team
##
df_wyscout_team_grouped = (df_wyscout_fixture_grouped
.groupby(['League_Name', 'Team', 'Event'])
.agg({'Team_Value': ['sum'],
'Opponent_Value': ['sum']
}
)
)
##
df_wyscout_team_grouped.columns = df_wyscout_team_grouped.columns.droplevel(level=0)
##
df_wyscout_team_grouped = df_wyscout_team_grouped.reset_index()
## Rename columns
df_wyscout_team_grouped.columns = ['League_Name', 'Team', 'Event', 'Team_Value', 'Opponent_Value']
## Display columns
df_wyscout_team_grouped.head()
League_Name | Team | Event | Team_Value | Opponent_Value | |
---|---|---|---|---|---|
0 | Bundesliga | Augsburg | Duel | 7240 | 7292 |
1 | Bundesliga | Augsburg | Foul | 497 | 433 |
2 | Bundesliga | Augsburg | Free Kick | 1660 | 1686 |
3 | Bundesliga | Augsburg | Goalkeeper leaving line | 41 | 42 |
4 | Bundesliga | Augsburg | Offside | 73 | 28 |
df_wyscout_team_grouped.to_csv(data_dir_wyscout + '/engineered/combined/wyscout_aggregated_team_big5_1718.csv', index=None, header=True)