{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-02-21T17:11:07.002058Z","iopub.execute_input":"2022-02-21T17:11:07.002639Z","iopub.status.idle":"2022-02-21T17:11:07.011941Z","shell.execute_reply.started":"2022-02-21T17:11:07.002604Z","shell.execute_reply":"2022-02-21T17:11:07.010010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import missingno as msno\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport matplotlib.gridspec as gridspec","metadata":{"execution":{"iopub.status.busy":"2022-02-21T19:49:14.643411Z","iopub.execute_input":"2022-02-21T19:49:14.644329Z","iopub.status.idle":"2022-02-21T19:49:14.649253Z","shell.execute_reply.started":"2022-02-21T19:49:14.644280Z","shell.execute_reply":"2022-02-21T19:49:14.648420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.set_option('display.max_columns', None)\n\ndf_train = pd.read_csv('/kaggle/input/football-match-probability-prediction/train.csv')\ndf_test = pd.read_csv('/kaggle/input/football-match-probability-prediction/test.csv')","metadata":{"execution":{"iopub.status.busy":"2022-02-21T17:11:09.660646Z","iopub.execute_input":"2022-02-21T17:11:09.661315Z","iopub.status.idle":"2022-02-21T17:11:19.136695Z","shell.execute_reply.started":"2022-02-21T17:11:09.661271Z","shell.execute_reply":"2022-02-21T17:11:19.135934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. First look at our data\n\nQuick look at the variables and which informations they hold.\n\nAfter this first look let´s make some assumptions about the relationships we might expect in our data","metadata":{}},{"cell_type":"code","source":"# - General look at the data structure -\ndf_train.head()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T18:36:24.006024Z","iopub.execute_input":"2022-02-21T18:36:24.006503Z","iopub.status.idle":"2022-02-21T18:36:24.212458Z","shell.execute_reply.started":"2022-02-21T18:36:24.006467Z","shell.execute_reply":"2022-02-21T18:36:24.211724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# - Taking a look at the number of rows and the variable type of them -\ndf_train.info() ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1.1. Making assumptions\n\nOur assumptions:\n* **home team** has **advantage on winning** the game - especially when the match is in a cup\n\n* **first** few **games of new coach** the team will peform **worse**\n\n* the **more rested** the team, the **better it will perform**\n\n* win/loss **streak will continue**\n\n* **rating** from** past games** will **influence** also\n\n* league id is not that important","metadata":{}},{"cell_type":"code","source":"# - Auxiliar functions -\n\n# get the name of the winning team\ndef column_winner(row):\n    if row['target']=='away':\n        return row['away_team_name']\n    elif row['target']=='home':\n        return row['home_team_name']\n    else:\n        return 'draw'\n\n# get the name of the losing team\ndef column_loser(row):\n    if row['target']=='away':\n        return row['home_team_name']\n    elif row['target']=='home':\n        return row['away_team_name']\n    else:\n        return 'draw'\n\n# when the currently coach joined the team\ndef time_coach(row,h_a):\n    coach_id = row['{}_team_coach_id'.format(h_a)]\n    time = 1\n    for match in range(1,11):\n        if row['{}_team_history_coach_{}'.format(h_a,match)]==coach_id:\n            time = time+1\n        elif np.isnan(row['{}_team_history_coach_{}'.format(h_a,match)]):\n            time = np.nan\n            break\n        else:\n            break\n    return time\n\n# t - (t-1)\ndef time_elapsed_between_matches(row,match_id, h_a):\n    if match_id==1:\n        time_elapsed = row['match_date'] - row['{}_team_history_match_date_1'.format(h_a)]\n    else:\n        time_elapsed = row['{}_team_history_match_date_{}'.format(h_a,match_id-1)] - row['{}_team_history_match_date_{}'.format(h_a,match_id)]\n    \n    return time_elapsed.total_seconds()\n\n# rest score using the sum of (1-alpha)^(period)*(rest_time) -> rest in recent matches have bigger weight on the score\ndef rest_score(row,h_a,alpha):\n    score = 0\n    for hist in range(1,11):\n        if hist==1:\n            score = alpha*row['{}_rest_time_{}'.format(h_a,hist)]\n        else:\n            score = score + (((1-alpha)**(hist-1))*row['{}_rest_time_{}'.format(h_a,hist)])\n\n    return score\n\n# History Match Result ---- If they scored more goals then conceived -> win, if it's equal -> draw, if they conceived more -> loss\ndef win_loss_history(row,h_a,hist):\n    goals_scored = row['{}_team_history_goal_{}'.format(h_a,hist)]\n    goals_conceived = row['{}_team_history_opponent_goal_{}'.format(h_a,hist)]\n    \n    if goals_scored==goals_conceived:\n        return 'draw'\n    elif goals_scored>goals_conceived:\n        return 'win'\n    else:\n        return 'loss'\n\n# Functions to calculate the result streak\ndef win_streak(row,h_a):\n    streak=0\n    for hist in range(1,11):\n        if row['{}_match_result_{}'.format(h_a,hist)]=='win':\n            streak=streak+1\n        else:\n            break\n    return streak\ndef loss_streak(row,h_a):\n    streak=0\n    for hist in range(1,11):\n        if row['{}_match_result_{}'.format(h_a,hist)]=='loss':\n            streak=streak+1\n        else:\n            break\n    return streak\ndef draw_streak(row,h_a):\n    streak=0\n    for hist in range(1,11):\n        if row['{}_match_result_{}'.format(h_a,hist)]=='draw':\n            streak=streak+1\n        else:\n            break\n    return streak\n\n# Calculating points of the last games - draw = +1 -> win = +3 -> loss = +0\ndef point_matches(row,h_a):\n    point=0\n    for hist in range(1,11):\n        if row['{}_match_result_{}'.format(h_a,hist)]=='draw':\n            point=point+1\n        elif row['{}_match_result_{}'.format(h_a,hist)]=='win':\n            point = point+3\n    \n    return point\n\n# - Function for creating new variables on the dataframe based on our assumptions - Bringing all pother functions together \ndef new_variables(df, type_df = 'train'):\n    new_df = df.copy()\n    \n    # transforming match_date to datetime\n    new_df['match_date'] = pd.to_datetime(new_df['match_date'])\n    \n    # Creating column with the winning and losing team\n    if type_df=='train':\n        new_df['winning_team'] = new_df.apply(column_winner, axis=1)\n        new_df['losing_team'] = new_df.apply(column_loser, axis=1)\n    \n    # looping through 'home' and 'away' team\n    for h_a in ['home','away']:\n        # getting match time with the currently coach\n        new_df['time_{}_coach'.format(h_a)] = new_df.apply(time_coach, h_a=h_a, axis=1)\n        for time in range(1,11):\n            # Transforming to datetime the history matches\n            new_df['{}_team_history_match_date_{}'.format(h_a,time)] = pd.to_datetime(new_df['{}_team_history_match_date_{}'.format(h_a,time)])\n            # Calculating the time elapsed between matches\n            new_df['{}_rest_time_{}'.format(h_a,time)] = new_df.apply(time_elapsed_between_matches,args=(time,h_a), axis=1)\n            # Getting the result of history matches\n            new_df['{}_match_result_{}'.format(h_a,time)] = new_df.apply(win_loss_history, args=(h_a,time), axis=1)\n    \n    # looping through 'home' and 'away' team again\n    for h_a in ['home','away']:\n        # Calcuating the rest score for the currently game\n        new_df['{}_rest_score'.format(h_a)] = new_df.apply(rest_score,args=(h_a,0.6),axis=1)\n        # Calculating the result streak\n        new_df['{}_win_streak'.format(h_a)] = new_df.apply(win_streak,h_a=h_a,axis=1)\n        new_df['{}_loss_streak'.format(h_a)] = new_df.apply(loss_streak,h_a=h_a,axis=1)\n        new_df['{}_draw_streak'.format(h_a)] = new_df.apply(draw_streak,h_a=h_a,axis=1)\n        # Calculating points of the last games\n        new_df['{}_last_points'.format(h_a)] = new_df.apply(point_matches,h_a=h_a,axis=1)\n        \n    # create column if match is a friendly or not\n    new_df['Friendly'] = 0\n    new_df.loc[new_df['league_name']=='Club Friendlies','Friendly'] = 1\n    \n    return new_df","metadata":{"execution":{"iopub.status.busy":"2022-02-21T17:11:27.389589Z","iopub.execute_input":"2022-02-21T17:11:27.389923Z","iopub.status.idle":"2022-02-21T17:11:27.417221Z","shell.execute_reply.started":"2022-02-21T17:11:27.389885Z","shell.execute_reply":"2022-02-21T17:11:27.416377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Calling the previous function\ndf_train = new_variables(df_train)","metadata":{"execution":{"iopub.status.busy":"2022-02-21T17:11:33.172297Z","iopub.execute_input":"2022-02-21T17:11:33.172966Z","iopub.status.idle":"2022-02-21T17:21:51.832460Z","shell.execute_reply.started":"2022-02-21T17:11:33.172933Z","shell.execute_reply":"2022-02-21T17:21:51.831707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Data Visualization\n\nVisual analysis of our dataset to see with our assumptions were correct\n\nAnalysis if there are any other relationship we might have forgoten","metadata":{}},{"cell_type":"code","source":"# First config for our plots\nsns.set_palette(\"Reds\")\nsns.set_style(\"whitegrid\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20,20))\ng = gridspec.GridSpec(2,2)\n\nax1= plt.subplot(g[0,0])\nax2= plt.subplot(g[0,1])\nax3= plt.subplot(g[1,:])\naxs=[ax1,ax2,ax3]\n\n# Count for each type of Result\ncnt_target = df_train['target'].value_counts(normalize=True).rename('Percentage').mul(100).reset_index().sort_values('index')\nsns.barplot(x='index',y='Percentage',data=cnt_target,ax=axs[0]).set(title=\"Match result distribution\",ylabel='Percentage',xlabel='Result')\n# Matches if is cup or not\nsns.countplot(x='is_cup',data=df_train,ax=axs[1]).set(title=\"Matches that are cup\",ylabel='Match count',xlabel='Is cup?')\n# Result per home and away team\nimpact_cup = df_train.groupby(['is_cup'])['target'].value_counts(normalize=True).rename('percentage').mul(100).reset_index().sort_values('target')\nax = sns.barplot(x='target',y='percentage',hue='is_cup',data=impact_cup,ax=axs[2]).set(title=\"Match result if it's a cup match or not\",ylabel='Percentage',xlabel='Result')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:07:36.253202Z","iopub.execute_input":"2022-02-21T20:07:36.253461Z","iopub.status.idle":"2022-02-21T20:07:37.011382Z","shell.execute_reply.started":"2022-02-21T20:07:36.253431Z","shell.execute_reply":"2022-02-21T20:07:37.010690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Number of teams\nprint(\"There are {} teams on the training dataset\".format(pd.concat([df_train['home_team_name'],df_train['away_team_name']]).unique().shape[0]))\n# Teams with most wins/loss/draws\nfig, axs = plt.subplots(ncols=3,figsize=(35,15))\ndf_without_draw = df_train.loc[df_train['winning_team']!='draw',:]\ndf_draw = df_train.loc[df_train['winning_team']=='draw',:]\n# win per team\ngrouped_wins = df_without_draw.groupby(['league_name'])['winning_team'].value_counts().rename('value').reset_index().sort_values(by='value')\naux_wins = grouped_wins.groupby(['winning_team'])['value'].sum().reset_index().sort_values(by='value', ascending=False).head(20)\nsns.barplot(y='winning_team',x='value',data=aux_wins, ax=axs[0]).set(title=\"Team with the most wins\",ylabel='Team',xlabel='Win count')\n# loss per team\ngrouped_loss = df_without_draw.groupby(['league_name'])['losing_team'].value_counts().rename('value').reset_index().sort_values(by='value')\naux_loss = grouped_loss.groupby(['losing_team'])['value'].sum().reset_index().sort_values(by='value', ascending=False).head(20)\nsns.barplot(y='losing_team',x='value',data=aux_loss, ax=axs[1]).set(title=\"Team with the most loss\",ylabel='Team',xlabel='Loss count')\n# draw per team\naux_draw = pd.concat([df_draw['home_team_name'],df_draw['away_team_name']]).value_counts().rename('value').reset_index().sort_values(by='value',ascending=False).head(20)\nsns.barplot(y='index',x='value',data=aux_draw, ax=axs[2]).set(title=\"Team with the most draws\",ylabel='Team',xlabel='Draw count')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:10:22.280651Z","iopub.execute_input":"2022-02-21T20:10:22.280946Z","iopub.status.idle":"2022-02-21T20:10:23.612315Z","shell.execute_reply.started":"2022-02-21T20:10:22.280910Z","shell.execute_reply":"2022-02-21T20:10:23.611596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Number of leagues\nprint(\"There are {} leagues on the training dataset\".format(aux_team_league['league_name'].unique().shape[0]-1))\nfig, axs = plt.subplots(ncols=2,figsize=(35,15))\n# Number of teams per league\naux_team_league = pd.concat([df_train[['home_team_name','league_name']].rename(columns={\"home_team_name\": \"team\"}),df_train[['away_team_name','league_name']].rename(columns={\"away_team_name\": \"team\"})]).drop_duplicates()\ngroup_league = aux_team_league.groupby(['league_name'])['team'].count().rename('value').reset_index().sort_values(by='value',ascending=False)\ngroup_league = group_league.loc[group_league['league_name']!='Club Friendlies',:].head(20)\nsns.barplot(y='league_name',x='value',data=group_league, ax=axs[0]).set(title=\"Leagues with the most teams\",ylabel='League',xlabel='Team count')\n\n# teamns with the most wins per each league (percentage) filter the leagues that have more than 200 matches\ngrouped_teams = pd.concat([df_train[['home_team_name','league_name']].rename(columns={\"home_team_name\": \"team\"}),df_train[['away_team_name','league_name']].rename(columns={\"away_team_name\": \"team\"})])\nleagues_with_matches = grouped_teams.groupby(['league_name']).count().rename(columns={\"team\": \"matches\"}).sort_values(by='matches', ascending=False)\nleagues_with_matches['matches'] = leagues_with_matches['matches']/2\nleagues_with_matches = leagues_with_matches.loc[leagues_with_matches['matches']>200,:]\naux_win_league = df_without_draw.loc[df_without_draw['league_name'].isin(leagues_with_matches.index),:].groupby(['league_name'])['winning_team'].value_counts(normalize=True).rename('Percentage').mul(100).reset_index().sort_values(by='Percentage',ascending=False).head(20)\nsns.barplot(y='winning_team',x='Percentage',data=aux_win_league, ax=axs[1]).set(title=\"Teams with biggest relative win per league\",ylabel='Team',xlabel='Win Percentage')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:12:31.956544Z","iopub.execute_input":"2022-02-21T20:12:31.956808Z","iopub.status.idle":"2022-02-21T20:12:32.885398Z","shell.execute_reply.started":"2022-02-21T20:12:31.956774Z","shell.execute_reply":"2022-02-21T20:12:32.884724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(25,15))\n# time of coach per result\nhome_team = df_train.loc[:,['target','time_home_coach']]\nhome_team.loc[home_team['target']=='home','target']='win'\nhome_team.loc[home_team['target']=='away','target']='loss'\naway_team = df_train.loc[:,['target','time_away_coach']]\naway_team.loc[away_team['target']=='away','target']='win'\naway_team.loc[away_team['target']=='home','target']='loss'\ngrouped_coach = pd.concat([home_team.rename(columns={\"time_home_coach\": \"time_coach\"}),away_team.rename(columns={\"time_away_coach\": \"time_coach\"})]).reset_index()\ngrouped_coach = grouped_coach.groupby(['time_coach'])['target'].value_counts(normalize=True).rename('Percentage').mul(100).reset_index()\nsns.barplot(data=grouped_coach,x='time_coach',y='Percentage',hue='target',ax=ax).set(title=\"Coach Match count per result\",xlabel='Match count')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:19:43.230983Z","iopub.execute_input":"2022-02-21T20:19:43.231396Z","iopub.status.idle":"2022-02-21T20:19:43.863408Z","shell.execute_reply.started":"2022-02-21T20:19:43.231355Z","shell.execute_reply":"2022-02-21T20:19:43.862725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(nrows=2,figsize=(15,25))\n# rest score per result\nhome_rest = df_train.loc[:,['target','home_rest_score']]\nhome_rest.loc[home_rest['target']=='home','target']='win'\nhome_rest.loc[home_rest['target']=='away','target']='loss'\naway_rest = df_train.loc[:,['target','away_rest_score']]\naway_rest.loc[away_rest['target']=='away','target']='win'\naway_rest.loc[away_rest['target']=='home','target']='loss'\ngrouped_rest = pd.concat([home_rest.rename(columns={\"home_rest_score\": \"rest_score\"}),away_rest.rename(columns={\"away_rest_score\": \"rest_score\"})]).reset_index()\ngrouped_rest['rest_score'] = np.log(grouped_rest['rest_score'])\nsns.boxplot(data=grouped_rest,y='rest_score',x='target',ax=axs[0]).set(title=\"Rest Score per Result\",ylabel='Rest Score')\nsns.kdeplot(data=grouped_rest,x='rest_score',hue='target',ax=axs[1]).set(title=\"Rest Score per Result\",xlabel='Rest Score')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:32:07.310162Z","iopub.execute_input":"2022-02-21T20:32:07.310431Z","iopub.status.idle":"2022-02-21T20:32:09.189619Z","shell.execute_reply.started":"2022-02-21T20:32:07.310400Z","shell.execute_reply":"2022-02-21T20:32:09.188923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(nrows=3,figsize=(15,25))\n# streak per result\nhome_streak = df_train.loc[:,['target','home_win_streak','home_loss_streak','home_draw_streak']]\nhome_streak.loc[home_streak['target']=='home','target']='win'\nhome_streak.loc[home_streak['target']=='away','target']='loss'\naway_streak = df_train.loc[:,['target','away_win_streak','away_loss_streak','away_draw_streak']]\naway_streak.loc[away_streak['target']=='away','target']='win'\naway_streak.loc[away_streak['target']=='home','target']='loss'\ngrouped_streak = pd.concat([home_streak.rename(columns={\"home_win_streak\": \"win_streak\",\"home_loss_streak\": \"loss_streak\",\"home_draw_streak\": \"draw_streak\"}),away_streak.rename(columns={\"away_win_streak\": \"win_streak\",\"away_loss_streak\": \"loss_streak\",\"away_draw_streak\": \"draw_streak\"})]).reset_index()\n\ngrouped_win_streak = grouped_streak.groupby(['win_streak'])['target'].value_counts(normalize=True).rename('Percentage').mul(100).reset_index()\nsns.barplot(data=grouped_win_streak,x='win_streak',y='Percentage',hue='target',ax=axs[0]).set(title=\"Win Streak per Result\",xlabel='Win Streak')\n\ngrouped_loss_streak = grouped_streak.groupby(['loss_streak'])['target'].value_counts(normalize=True).rename('Percentage').mul(100).reset_index()\nsns.barplot(data=grouped_loss_streak,x='loss_streak',y='Percentage',hue='target',ax=axs[1]).set(title=\"Loss Streak per Result\",xlabel='Loss Streak')\n\ngrouped_draw_streak = grouped_streak.groupby(['draw_streak'])['target'].value_counts(normalize=True).rename('Percentage').mul(100).reset_index()\nsns.barplot(data=grouped_draw_streak,x='draw_streak',y='Percentage',hue='target',ax=axs[2]).set(title=\"Draw Streak per Result\",xlabel='Draw Streak')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:34:19.995325Z","iopub.execute_input":"2022-02-21T20:34:19.996056Z","iopub.status.idle":"2022-02-21T20:34:21.153341Z","shell.execute_reply.started":"2022-02-21T20:34:19.996018Z","shell.execute_reply":"2022-02-21T20:34:21.152695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axs = plt.subplots(nrows=2,figsize=(15,25))\n# point per result\nhome_point = df_train.loc[:,['target','home_last_points']]\nhome_point.loc[home_point['target']=='home','target']='win'\nhome_point.loc[home_point['target']=='away','target']='loss'\naway_point = df_train.loc[:,['target','away_last_points']]\naway_point.loc[away_point['target']=='away','target']='win'\naway_point.loc[away_point['target']=='home','target']='loss'\ngrouped_point = pd.concat([home_point.rename(columns={\"home_last_points\": \"points\"}),away_point.rename(columns={\"away_last_points\": \"points\"})]).reset_index()\n\nsns.boxplot(data=grouped_point,y='points',x='target',ax=axs[0]).set(title=\"Points per Result\",ylabel='Points')\n\nsns.kdeplot(data=grouped_point,x='points',hue='target',ax=axs[1]).set(title=\"Points per Result\",xlabel='Points')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:36:17.832759Z","iopub.execute_input":"2022-02-21T20:36:17.833353Z","iopub.status.idle":"2022-02-21T20:36:19.645611Z","shell.execute_reply.started":"2022-02-21T20:36:17.833319Z","shell.execute_reply":"2022-02-21T20:36:19.644921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Conclusions\n\n* There is a bigger chance of winning when playing in home\n\n* When a match is a cup, there are fewer draws - maybe the teams take more risks\n\n* In the first few games of a new coach, there is a bigger chance of losing\n\n* No relationship between rest score and chance of winning or losing\n\n* The bigger the win/loss streak bigger is the chance of the streak to continue\n\n* Existing relationship between points on the last games and match result","metadata":{}},{"cell_type":"markdown","source":"# **3. Missing Data**\n\n* Taking a look at the data the are missing\n\n* Creating a plan to handle those missing values","metadata":{}},{"cell_type":"code","source":"# - General look at the missing data using missigno library\nmsno.matrix(df_train) # Matrix of NaN - easy to see if there are any missing data and if there is a pattern\nplt.show()\nmsno.heatmap(df_train) # Correlation between the Null variables of each column\nplt.show()\nmsno.dendrogram(df_train) # Easy to visualize, correlation between null of each column\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-21T20:38:12.607344Z","iopub.execute_input":"2022-02-21T20:38:12.607687Z","iopub.status.idle":"2022-02-21T20:39:43.461094Z","shell.execute_reply.started":"2022-02-21T20:38:12.607651Z","shell.execute_reply":"2022-02-21T20:39:43.459191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.set_option('display.max_rows', None)\ndf_train.isna().sum()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **4. Final adjustment before training**\n\n* Choosing variables that we are going to train on\n\n* Filling missing values\n\n* Log transformation on ratings history and rest score -> both have right skewed distribution\n\n* Dividing the dataset into variables and target\n\n* Scaling the variables (x)","metadata":{}},{"cell_type":"code","source":"# Function to adjust the skeweness and missing value of variables\ndef df_adjustment(df, df_type='train'):\n    new_df = df.copy()\n    \n    if df_type=='train':\n        features = ['target','is_cup',\n                   'home_team_history_rating_1','home_team_history_rating_2','home_team_history_rating_3','home_team_history_rating_4','home_team_history_rating_5','home_team_history_rating_6','home_team_history_rating_7','home_team_history_rating_8','home_team_history_rating_9','home_team_history_rating_10',\n                  'home_team_history_opponent_rating_1','home_team_history_opponent_rating_2','home_team_history_opponent_rating_3','home_team_history_opponent_rating_4','home_team_history_opponent_rating_5','home_team_history_opponent_rating_6','home_team_history_opponent_rating_7','home_team_history_opponent_rating_8','home_team_history_opponent_rating_9','home_team_history_opponent_rating_10',\n                  'away_team_history_rating_1','away_team_history_rating_2','away_team_history_rating_3','away_team_history_rating_4','away_team_history_rating_5','away_team_history_rating_6','away_team_history_rating_7','away_team_history_rating_8','away_team_history_rating_9','away_team_history_rating_10',\n                  'away_team_history_opponent_rating_1','away_team_history_opponent_rating_2','away_team_history_opponent_rating_3','away_team_history_opponent_rating_4','away_team_history_opponent_rating_5','away_team_history_opponent_rating_6','away_team_history_opponent_rating_7','away_team_history_opponent_rating_8','away_team_history_opponent_rating_9','away_team_history_opponent_rating_10',\n                  'time_home_coach','time_away_coach','home_rest_score','away_rest_score',\n                  'home_win_streak','away_win_streak','home_loss_streak','away_loss_streak','home_draw_streak','away_draw_streak',\n                  'home_last_points', 'away_last_points',\n                  'Friendly']\n    else:\n        features = ['is_cup',\n                   'home_team_history_rating_1','home_team_history_rating_2','home_team_history_rating_3','home_team_history_rating_4','home_team_history_rating_5','home_team_history_rating_6','home_team_history_rating_7','home_team_history_rating_8','home_team_history_rating_9','home_team_history_rating_10',\n                  'home_team_history_opponent_rating_1','home_team_history_opponent_rating_2','home_team_history_opponent_rating_3','home_team_history_opponent_rating_4','home_team_history_opponent_rating_5','home_team_history_opponent_rating_6','home_team_history_opponent_rating_7','home_team_history_opponent_rating_8','home_team_history_opponent_rating_9','home_team_history_opponent_rating_10',\n                  'away_team_history_rating_1','away_team_history_rating_2','away_team_history_rating_3','away_team_history_rating_4','away_team_history_rating_5','away_team_history_rating_6','away_team_history_rating_7','away_team_history_rating_8','away_team_history_rating_9','away_team_history_rating_10',\n                  'away_team_history_opponent_rating_1','away_team_history_opponent_rating_2','away_team_history_opponent_rating_3','away_team_history_opponent_rating_4','away_team_history_opponent_rating_5','away_team_history_opponent_rating_6','away_team_history_opponent_rating_7','away_team_history_opponent_rating_8','away_team_history_opponent_rating_9','away_team_history_opponent_rating_10',\n                  'time_home_coach','time_away_coach','home_rest_score','away_rest_score',\n                  'home_win_streak','away_win_streak','home_loss_streak','away_loss_streak','home_draw_streak','away_draw_streak',\n                  'home_last_points', 'away_last_points',\n                  'Friendly']\n    \n    new_df = new_df.loc[:,features]\n    \n    # missing is_cup values equals to 0 -> most of matches are not cup\n    new_df['is_cup'] = new_df['is_cup'].fillna(0)\n    \n    for h_a in ['home','away']:\n        # time of coach on team will be +11 matches as is the most commom value\n        new_df['time_{}_coach'.format(h_a)] = new_df['time_{}_coach'.format(h_a)].fillna(11)\n        # rest_score is filled with the median value\n        new_df['{}_rest_score'.format(h_a)] =  np.log(new_df['{}_rest_score'.format(h_a)].fillna(new_df['{}_rest_score'.format(h_a)].median()))\n        for hist in range(1,11):\n            # rating values will be first grouped by team and if is played in home\n            new_df['{}_team_history_rating_{}'.format(h_a,hist)] = new_df['{}_team_history_rating_{}'.format(h_a,hist)].fillna(df.groupby(['{}_team_name'.format(h_a),'{}_team_history_is_play_home_1'.format(h_a)])['{}_team_history_rating_1'.format(h_a)].transform('median'))\n            new_df['{}_team_history_opponent_rating_{}'.format(h_a,hist)] = new_df['{}_team_history_opponent_rating_{}'.format(h_a,hist)].fillna(df.groupby(['{}_team_name'.format(h_a),'{}_team_history_is_play_home_1'.format(h_a)])['{}_team_history_opponent_rating_1'.format(h_a)].transform('median'))\n            # the still missing values are completed with the median value of all ratings\n            new_df['{}_team_history_rating_{}'.format(h_a,hist)] =  np.log(new_df['{}_team_history_rating_{}'.format(h_a,hist)].fillna(df['{}_team_history_rating_1'.format(h_a)].median()))\n            new_df['{}_team_history_opponent_rating_{}'.format(h_a,hist)] =  np.log(new_df['{}_team_history_opponent_rating_{}'.format(h_a,hist)].fillna(df['{}_team_history_opponent_rating_1'.format(h_a)].median()))\n    return new_df\n    ","metadata":{"execution":{"iopub.status.busy":"2022-02-21T18:41:06.485246Z","iopub.execute_input":"2022-02-21T18:41:06.485572Z","iopub.status.idle":"2022-02-21T18:41:06.501956Z","shell.execute_reply.started":"2022-02-21T18:41:06.485539Z","shell.execute_reply":"2022-02-21T18:41:06.501201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Dividing the dataset into variables and target\nmod_df = df_adjustment(df_train)\n\nx = mod_df.drop(columns=['target'])\ny = mod_df.loc[:,'target']","metadata":{"execution":{"iopub.status.busy":"2022-02-21T18:41:08.801588Z","iopub.execute_input":"2022-02-21T18:41:08.801849Z","iopub.status.idle":"2022-02-21T18:41:10.867808Z","shell.execute_reply.started":"2022-02-21T18:41:08.801819Z","shell.execute_reply":"2022-02-21T18:41:10.867000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Scaling the features\nfrom sklearn.preprocessing import StandardScaler\n\nscaler = StandardScaler()\nx = pd.DataFrame(scaler.fit_transform(x),columns=x.columns)","metadata":{"execution":{"iopub.status.busy":"2022-02-21T18:46:17.996837Z","iopub.execute_input":"2022-02-21T18:46:17.997701Z","iopub.status.idle":"2022-02-21T18:46:19.971440Z","shell.execute_reply.started":"2022-02-21T18:46:17.997655Z","shell.execute_reply":"2022-02-21T18:46:19.970415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **5. Choosing and training our model**\n\n* Choosing best model for our dataset\n\n* Tuning the hyperparameter\n\n\n* Training the model","metadata":{}},{"cell_type":"markdown","source":"# Code for getting best model with cross validation\n\nfrom sklearn.neural_network import MLPClassifier\nfrom sklearn.neighbors import KNeighborsClassifier \nfrom sklearn.svm import SVC \nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.gaussian_process import GaussianProcessClassifier \nfrom sklearn.gaussian_process.kernels import RBF \nfrom sklearn.tree import DecisionTreeClassifier \nfrom sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier \nfrom sklearn.naive_bayes import GaussianNB \nfrom sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis\n\nclassifiers = [MLPClassifier(),KNeighborsClassifier(),SVC(),LogisticRegression(),GaussianProcessClassifier(),RBF(),DecisionTreeClassifier(),RandomForestClassifier(),AdaBoostClassifier(),GradientBoostingClassifier(),GaussianNB(),QuadraticDiscriminantAnalysis()]\n\nfrom sklearn.model_selection import cross_val_score\n\nvalues = []\nfor model in classifiers:\n    new_value = cross_val_score(model,x,y,cv=3,scoring=\"neg_log_loss\")\n    values.append(new_value)\n    print(f\"{model} - {new_value}\")\n    ","metadata":{"execution":{"iopub.status.busy":"2022-02-21T19:00:55.449347Z","iopub.execute_input":"2022-02-21T19:00:55.449609Z","iopub.status.idle":"2022-02-21T19:19:55.714285Z","shell.execute_reply.started":"2022-02-21T19:00:55.449580Z","shell.execute_reply":"2022-02-21T19:19:55.713540Z"}}},{"cell_type":"markdown","source":"# Code for tuning the hyperparameters of our best model\n\n#Tuning Hyperparameters\nfrom sklearn.model_selection import GridSearchCV\nfrom sklearn.linear_model import LogisticRegression\n\nparam_grid={\"C\":np.logspace(-3,3,7), \"solver\":[\"newton-cg\",\"lbfgs\",\"liblinear\",\"sag\",\"saga\"]}\ngrid = GridSearchCV(LogisticRegression(),param_grid,verbose=2,cv=3,scoring=\"neg_log_loss\")\ngrid.fit(x,y)\n\nprint(grid.best_score_)\nprint(grid.best_params_)","metadata":{"execution":{"iopub.status.busy":"2022-02-21T19:27:34.426052Z","iopub.execute_input":"2022-02-21T19:27:34.426782Z","iopub.status.idle":"2022-02-21T19:32:45.486012Z","shell.execute_reply.started":"2022-02-21T19:27:34.426732Z","shell.execute_reply":"2022-02-21T19:32:45.483121Z"}}},{"cell_type":"code","source":"# Creating and training our model\nfrom sklearn.linear_model import LogisticRegression\n\nmodel = LogisticRegression(C=0.001,penalty='l2',solver='lbfgs')\nmodel.fit(x,y)","metadata":{"execution":{"iopub.status.busy":"2022-02-21T16:24:32.158556Z","iopub.execute_input":"2022-02-21T16:24:32.158814Z","iopub.status.idle":"2022-02-21T16:24:34.482151Z","shell.execute_reply.started":"2022-02-21T16:24:32.158786Z","shell.execute_reply":"2022-02-21T16:24:34.481515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **6. Making predictions**\n\n* Preparing our test dataframe\n\n* Making the predictions","metadata":{}},{"cell_type":"code","source":"# Preparing the test dataset\n\ntest_df_mod = new_variables(df_test, 'test')\ntest_df_mod2 = df_adjustment(test_df_mod,'test')\ntest_df_ok = pd.DataFrame(scaler.transform(test_df_mod2),columns=test_df_mod2.columns)","metadata":{"execution":{"iopub.status.busy":"2022-02-21T16:25:51.490257Z","iopub.execute_input":"2022-02-21T16:25:51.490731Z","iopub.status.idle":"2022-02-21T16:32:46.463841Z","shell.execute_reply.started":"2022-02-21T16:25:51.490696Z","shell.execute_reply":"2022-02-21T16:32:46.46313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Making the predictions\n\npredictions = model.predict_proba(test_df_ok)\nsubmission = pd.concat([pd.DataFrame(df_test.id),pd.DataFrame(predictions,columns=['away','draw','home'])[['home', 'draw','away']]],axis=1).set_index('id')\nsubmission.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2022-02-21T16:38:16.343844Z","iopub.execute_input":"2022-02-21T16:38:16.344103Z","iopub.status.idle":"2022-02-21T16:38:16.385737Z","shell.execute_reply.started":"2022-02-21T16:38:16.344073Z","shell.execute_reply":"2022-02-21T16:38:16.384875Z"},"trusted":true},"execution_count":null,"outputs":[]}]}