{"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":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom matplotlib import style\n\ndf = pd.read_csv(\"../input/football-match-probability-prediction/train.csv\")\nfor i in df.columns:\n    print(i)\n    \n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-22T10:34:20.343583Z","iopub.execute_input":"2022-03-22T10:34:20.343961Z","iopub.status.idle":"2022-03-22T10:34:26.616052Z","shell.execute_reply.started":"2022-03-22T10:34:20.343872Z","shell.execute_reply":"2022-03-22T10:34:26.613459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I would also suggest taking a look at this EDA by a different kaggle user: https://www.kaggle.com/aliphya/football-match-probability-prediction-eda","metadata":{}},{"cell_type":"markdown","source":"# Exploring Team Performances (Home & Away games + cup games)","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nfrom matplotlib.pyplot import figure\n\n\ndef without_hue(ax, feature,shift=0.08):\n    total = len(feature)\n    for p in ax.patches:\n        percentage = '{:.1f}%'.format(100 * p.get_height()/total)\n        x = p.get_x() + p.get_width() / 2 - shift\n        y = p.get_y() + p.get_height()\n        ax.annotate(percentage, (x, y), size = 36)\n\n\nfeatures = ['target','is_cup']\nsns.color_palette(\"crest\", as_cmap=True)\n\nfor col in features:\n    figure(figsize=(30, 10), dpi=80)\n    ax = sns.countplot(x = df[col])\n    plt.title(col, fontsize=40)\n    ax.set_xlabel(col, fontsize=20)\n    ax.set_ylabel('Count',fontsize=20)\n    without_hue(ax,df[col])\n    ax.tick_params(axis='both', which='major', labelsize=18)\n    plt.show()\n\n    \n","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:34:26.61805Z","iopub.execute_input":"2022-03-22T10:34:26.618815Z","iopub.status.idle":"2022-03-22T10:34:28.691494Z","shell.execute_reply.started":"2022-03-22T10:34:26.618767Z","shell.execute_reply":"2022-03-22T10:34:28.690556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"target - The target is characterized as the outcome of a match. 'Home' means that the home team won, 'Away' means that the away team won and 'Draw' means that the game resulted in a draw. The data is fairly balanced with 'Home' making up 41% of the targets. This does make sense as the home team is generally seen as having an advantage due to familiarity with the pitch and support from fans during the game.\n\nis_cup - The vast majority of games are not cup games. One idea could be to create a seperate model for cup games as the patterns between cup and league game may differ, especially for cup games that play with the home advantage rules.","metadata":{}},{"cell_type":"markdown","source":"The win/draw/loss rates don't change very much across league, cup and frienly matches. The only noticable difference is that cup games have a bit more away wins, friendly games have more home wins and league games have more draws.","metadata":{}},{"cell_type":"code","source":"figure(figsize=(30, 10), dpi=80)\nn = 15\nsns.color_palette(\"crest\", as_cmap=True)\n\ncol = 'league_name'\nleagues = df['league_id'].value_counts()[:n].index.tolist()\nax = sns.countplot(x = df[df['league_id'].isin(leagues)][col])\nplt.title(\"Top 15 most represented leagues\",fontsize=30)\nax.set_xlabel(col, fontsize=20)\nax.set_ylabel('Count',fontsize=20)\nwithout_hue(ax,df['league_id'],shift=0.35)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:34:28.692941Z","iopub.execute_input":"2022-03-22T10:34:28.693257Z","iopub.status.idle":"2022-03-22T10:34:29.245332Z","shell.execute_reply.started":"2022-03-22T10:34:28.693214Z","shell.execute_reply":"2022-03-22T10:34:29.244388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The distribution of leagues is fairly even with the small exception of \"Club Friendlies\". One idea could be to filter out all club friendlies or add them as a seperate feature similar to is_cup since many teams don't field strong XIs for such games. Note that the plot only displays the top 15 represented leagues which only make up a small part of the data.","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\nfrom matplotlib.pyplot import figure\n\n\n    \n\ndf2 = df.copy(deep=True)\ndf2.loc[df2['is_cup'] == False,'game_type'] = 'League'\ndf2.loc[df2['is_cup'] == True,'game_type'] = 'Cup'\ndf2.loc[df2['league_name'] == 'Club Friendlies','game_type'] = 'Friendly'\n\ndf1 = df2.groupby('game_type')['target'].value_counts(normalize=True)\ndf1 = df1.mul(100)\ndf1 = df1.rename('percent').reset_index()\n\nfeatures = ['target','game_type']\nsns.color_palette(\"crest\", as_cmap=True)\nfigure(figsize=(30, 10), dpi=80)\nsns.set(font_scale=3)  # crazy big\n\ng = sns.catplot(x=\"game_type\",y='percent',hue='target',kind='bar',data=df1,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate for different competitions types\", fontsize=40)\ng.set_axis_labels(\"Competition Type\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(2)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()\n\n\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:34:29.247963Z","iopub.execute_input":"2022-03-22T10:34:29.248722Z","iopub.status.idle":"2022-03-22T10:34:30.118541Z","shell.execute_reply.started":"2022-03-22T10:34:29.248675Z","shell.execute_reply":"2022-03-22T10:34:30.117723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s = 'away_team_history_rating_'\ns2 = 'home_team_history_rating_'\ns3 = 'away_team_history_opponent_rating_'\ns4 = 'home_team_history_opponent_rating_'\ns_id = 'away_team_history_league_id'\ns_id = 'home_team_history_league_id'\n\np = \"away_team_history_is_play_home_\"\np2 = \"home_team_history_is_play_home_\"\np3 = \"away_team_opponent_history_is_play_home_\"\np4 = \"home_team_opponent_history_is_play_home_\"\n\ncolumn_names = [\"date\"]\nnew_df = pd.DataFrame(columns = column_names)\n\nhistory_df = df.loc[:, df.columns.str.contains(p)|df.columns.str.contains(p2)\\\n                    |df.columns.str.contains(s)|df.columns.str.contains(s2)|df.columns.str.contains(s3)|df.columns.str.contains(s4)|(df.columns == 'id')|(df.columns=='match_date')]\nhistory_df = pd.wide_to_long(history_df, stubnames=[s,s2,s3,s4,p,p2,p3,p4], i=\"id\",j='i')\n\n\nstyle.use(style='seaborn')\nplt.figure(figsize=(30,10))\n\n\nhistory_df.loc[history_df[p2]==0.0,p4] = 'home'\nhistory_df.loc[history_df[p2]==1.0,p4] = 'away'\nhistory_df.loc[history_df[p]==0.0,p3] = 'home'\nhistory_df.loc[history_df[p]==1.0,p3] = 'away'\n\n\nhistory_df.loc[history_df[p2]==0.0,p2] = 'away'\nhistory_df.loc[history_df[p2]==1.0,p2] = 'home'\nhistory_df.loc[history_df[p]==0.0,p] = 'away'\nhistory_df.loc[history_df[p]==1.0,p] = 'home'\n\norder = ['home','away']\n\nsns.set(font_scale=3)  # crazy big\n\nres = pd.DataFrame(columns=['ratings','home_or_away'])\nps = [p,p2]\nfor i, v in enumerate([s,s2]):\n    temp = history_df[[v,ps[i]]]\n    temp.rename(columns={v: 'ratings', ps[i]: 'home_or_away'}, inplace=True)\n    res = pd.concat([res,temp], axis=0)\nres.reset_index(inplace=True)\nax = sns.displot(res,x='ratings',fill=True,element=\"step\",kde=False,rug=False,hue='home_or_away',height=15,aspect=3,hue_order=order,stat=\"probability\")\nax.set_axis_labels(\"Team Rating\",\"Probability\")\nplt.title(\"Rating history at home vs away\")\nplt.show()\n\n\nres = pd.DataFrame(columns=['ratings','home_or_away'])\nps = [p3,p4]\nfor i, v in enumerate([s3,s4]):\n    temp = history_df[[v,ps[i]]]\n    temp.rename(columns={v: 'ratings', ps[i]: 'home_or_away'}, inplace=True)\n    res = pd.concat([res,temp], axis=0)\nres.reset_index(inplace=True)\nax = sns.displot(res,x='ratings',fill=True,element=\"step\",kde=False,rug=False,hue='home_or_away',height=15,aspect=3,hue_order=order,stat=\"probability\")\nax.set_axis_labels(\"Team Rating\",\"Probability\")\nplt.title(\"Opponent Rating history at home vs away\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:34:30.119904Z","iopub.execute_input":"2022-03-22T10:34:30.120721Z","iopub.status.idle":"2022-03-22T10:34:55.796388Z","shell.execute_reply.started":"2022-03-22T10:34:30.120676Z","shell.execute_reply":"2022-03-22T10:34:55.795477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"By stacking and visualizing the history ratings over home and away games, we can clearly see that match ratings are generally higher when playing at home.","metadata":{}},{"cell_type":"code","source":"s2 = 'away_team_history_goal_'\ns = 'home_team_history_goal_'\ns4 = 'away_team_history_opponent_goal_'\ns3 = 'home_team_history_opponent_goal_'\ns_id = 'away_team_history_league_id'\ns_id = 'home_team_history_league_id'\n\np2 = \"away_team_history_is_play_home_\"\np = \"home_team_history_is_play_home_\"\np4 = \"away_team_opponent_history_is_play_home_\"\np3 = \"home_team_opponent_history_is_play_home_\"\n\ncolumn_names = [\"date\"]\norder = ['home','away']\n\nnew_df = pd.DataFrame(columns = column_names)\n\nhistory_df = df.loc[:, df.columns.str.contains(p)|df.columns.str.contains(p2)\\\n                    |df.columns.str.contains(s)|df.columns.str.contains(s2)|df.columns.str.contains(s3)|df.columns.str.contains(s4)|(df.columns == 'id')|(df.columns=='match_date')]\nhistory_df = pd.wide_to_long(history_df, stubnames=[s,s2,s3,s4,p,p2,p3,p4], i=\"id\",j='i')\n\n\nstyle.use(style='seaborn')\nplt.figure(figsize=(30,10))\n\n\nhistory_df.loc[history_df[p2]==1.0,p4] = 'home'\nhistory_df.loc[history_df[p2]==0.0,p4] = 'away'\nhistory_df.loc[history_df[p]==1.0,p3] = 'home'\nhistory_df.loc[history_df[p]==0.0,p3] = 'away'\n\n\nhistory_df.loc[history_df[p2]==1.0,p2] = 'home'\nhistory_df.loc[history_df[p2]==0.0,p2] = 'away'\nhistory_df.loc[history_df[p]==1.0,p] = 'home'\nhistory_df.loc[history_df[p]==0.0,p] = 'away'\n\norder = ['home','away']\n\nsns.set(font_scale=3)  # crazy big\n\nres = pd.DataFrame(columns=['goals','home_or_away'])\nps = [p,p2]\nfor i, v in enumerate([s,s2]):\n    temp = history_df[[v,ps[i]]]\n    temp.rename(columns={v: 'goals', ps[i]: 'home_or_away'}, inplace=True)\n    res = pd.concat([res,temp])\nres.reset_index(inplace=True)\n\nax = sns.displot(x='goals',hue='home_or_away',element='bars',data=res,height=15,aspect=3,discrete=True,hue_order=order,stat=\"probability\")\nax.set_axis_labels(\"Team goal\",\"Probability\")\nplt.title(\"Goals scored as away team vs home team (historical features)\")\nplt.show()\n\n\nres = pd.DataFrame(columns=['goals','home_or_away'])\nps = [p3,p4]\nfor i, v in enumerate([s3,s4]):\n    temp = history_df[[v,ps[i]]]\n    temp.rename(columns={v: 'goals', ps[i]: 'home_or_away'}, inplace=True)\n    res = pd.concat([res,temp])\nres.reset_index(inplace=True)\n\nax = sns.displot(x='goals',hue='home_or_away',element='bars',data=res,height=15,aspect=3,discrete=True,hue_order=order,stat=\"probability\")\nax.set_axis_labels(\"Team goal\",\"Probability\")\nplt.title(\"Goals conceded as away team vs home team (historical features)\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:34:55.797691Z","iopub.execute_input":"2022-03-22T10:34:55.797915Z","iopub.status.idle":"2022-03-22T10:35:21.651828Z","shell.execute_reply.started":"2022-03-22T10:34:55.797888Z","shell.execute_reply":"2022-03-22T10:35:21.650967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"By adding up all counts of  goals scored/conceded aggregated by away/home sides, we can visualize how the distribution of goal scoring changes depending on whether or not a team is playing at home or away. One can see from the histograms that the home-team generally has a slight advantage as they more frequently score 2 or more goals. The away team also more frequently concede 2 or more goals.\n\nThe two plots are mirrors of each other since the goals score by the away team in the top plot is the same as goals conceded by the home team in the second plot.","metadata":{}},{"cell_type":"markdown","source":"# Match dates, match date history and seasonality","metadata":{}},{"cell_type":"code","source":"\ndf['date'] = pd.to_datetime(df['match_date'], errors='coerce')\nsns.set(font_scale=3)  # crazy big\n\nfigure(figsize=(30, 10), dpi=80)\nstyle.use(style='seaborn')\nax = df.groupby([df[\"date\"].dt.year, df[\"date\"].dt.month])['date'].count().plot(kind=\"bar\", x='Match Date', y='Count')\nax.set_title(\"Match Date distribution over year and month.\",fontsize=30)\nax.set_xlabel(\"Date (Year, Month)\",fontsize=20)\nax.set_ylabel(\"Amount of games\",fontsize=20)\nax.tick_params(axis='both', which='major', labelsize=18)\n","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:35:21.653037Z","iopub.execute_input":"2022-03-22T10:35:21.65327Z","iopub.status.idle":"2022-03-22T10:35:22.261314Z","shell.execute_reply.started":"2022-03-22T10:35:21.653241Z","shell.execute_reply":"2022-03-22T10:35:22.260402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"All games were played during the 2019/20 and 2020/21 seasons. This might cause an issue since many games might have been played without fans due to COVID19, which football fans know is a big disadvantage for the home teams. The advantage of having lots of data for only recent seasons is that the football that was played during this time should be fairly similar to the football that is played today in terms of tactics and playstyles.","metadata":{}},{"cell_type":"code","source":"s = 'away_team_history_match_date_'\ns2 = 'home_team_history_match_date_'\ns_id = 'away_team_history_league_id'\ns_id = 'home_team_history_league_id'\nsns.set(font_scale=3)  # crazy big\n\ncolumn_names = [\"date\"]\nnew_df = pd.DataFrame(columns = column_names)\n\nhistory_df = df.loc[:, df.columns.str.contains(s)| df.columns.str.contains(s2)|(df.columns == 'id')]\nhistory_df = pd.wide_to_long(history_df, stubnames=[s,s2], i=\"id\",j='i')\n\nhistory_df['home'] = pd.to_datetime(history_df['home_team_history_match_date_'], errors='coerce')\nhistory_df['away'] = pd.to_datetime(history_df['away_team_history_match_date_'], errors='coerce')\n\nhome_count = history_df.groupby([history_df[\"home\"].dt.year, history_df[\"home\"].dt.month])['home'].count()\naway_count = history_df.groupby([history_df[\"away\"].dt.year, history_df[\"away\"].dt.month])['away'].count()\n\n\nres = pd.concat([home_count, away_count], axis=1)\n\n\nstyle.use(style='seaborn')\nax = res.plot(kind=\"bar\",figsize=(30, 10))\nax.set_title(\"Match-Date History distribution over year and month.\",fontsize=30)\nax.set_xlabel(\"Date (Year, Month)\",fontsize=20)\nax.set_ylabel(\"Amount of games\",fontsize=20)\nax.tick_params(axis='both', which='major', labelsize=18)\nplt.show()\n\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:35:22.262745Z","iopub.execute_input":"2022-03-22T10:35:22.263044Z","iopub.status.idle":"2022-03-22T10:35:26.866328Z","shell.execute_reply.started":"2022-03-22T10:35:22.263004Z","shell.execute_reply":"2022-03-22T10:35:26.865545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The game history naturally spans a bit further back than the match-date feature.","metadata":{}},{"cell_type":"markdown","source":"# Win and Loss Streaks\n\nThis guy gave me the idea: https://www.kaggle.com/henriqueweber/football-results-prediction\n\nAdding wins and loss streaks might give extra insights into how we can predict results.","metadata":{}},{"cell_type":"code","source":"def add_streak(df):\n    h_t_goal = \"home_team_history_goal_\"\n    h_t_opp_goal = \"home_team_history_opponent_goal_\"\n    a_t_goal = \"away_team_history_goal_\"\n    a_t_opp_goal = \"away_team_history_opponent_goal_\"\n    df[\"away_streak\"] = np.nan\n    df[\"home_streak\"] = np.nan\n    df['streak_type'] = np.nan\n    def apply_streaks(x):\n        home_streak = 0\n        away_streak = 0\n        home_streak_over = False\n        away_streak_over = False\n        home_streak_type = None\n        away_streak_type = None\n        \n        if  x[h_t_goal+str(1)] > x[h_t_opp_goal+str(1)]:\n            home_win_streak = True\n            home_streak_type = 'win'\n        elif x[h_t_goal+str(1)] < x[h_t_opp_goal+str(1)]:\n            home_win_streak = False\n            home_streak_type = 'loss'\n        elif x[h_t_goal+str(1)] == x[h_t_opp_goal+str(1)]:\n            home_streak_type = 'draw'\n            \n        if  x[a_t_goal+str(1)] > x[a_t_opp_goal+str(1)]:\n            away_win_streak = True\n            away_streak_type = 'win'\n        elif x[a_t_goal+str(1)] < x[a_t_opp_goal+str(1)]:\n            away_win_streak = False\n            away_streak_type = 'loss'\n        elif x[a_t_goal+str(1)] == x[a_t_opp_goal+str(1)]:\n            away_streak_type = 'draw'\n            \n        def check_streak(streak,streak_over,streak_type,team_goal,opp_goal):\n            if not streak_over and streak_type=='win' and team_goal > opp_goal:\n                streak+=1\n            elif not streak_over and streak_type=='loss' and team_goal < opp_goal:\n                streak+=1\n            elif not streak_over and streak_type =='draw' and team_goal == opp_goal:\n                streak+=1\n            else:\n                streak_over = True\n            return streak, streak_over\n                \n        for i in range(1,11):\n            if not home_streak_over:\n                home_streak, home_streak_over = check_streak(home_streak,home_streak_over, home_streak_type, x[h_t_goal+str(i)],x[h_t_opp_goal+str(i)])\n            if not away_streak_over:\n                away_streak, away_streak_over = check_streak(away_streak,away_streak_over, away_streak_type, x[a_t_goal+str(i)],x[a_t_opp_goal+str(i)])\n            \n        return pd.Series([home_streak,home_streak_type,away_streak,away_streak_type],index=['home_streak','home_streak_type','away_streak','away_streak_type'])\n\n    \n    df[['home_streak','home_streak_type','away_streak','away_streak_type']] = df.apply(lambda x: apply_streaks(x), axis=1)\n    return df\n","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:35:26.867742Z","iopub.execute_input":"2022-03-22T10:35:26.86873Z","iopub.status.idle":"2022-03-22T10:35:26.887201Z","shell.execute_reply.started":"2022-03-22T10:35:26.868685Z","shell.execute_reply":"2022-03-22T10:35:26.886262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp_df = add_streak(df)","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:35:26.890307Z","iopub.execute_input":"2022-03-22T10:35:26.891222Z","iopub.status.idle":"2022-03-22T10:36:17.156666Z","shell.execute_reply.started":"2022-03-22T10:35:26.891173Z","shell.execute_reply":"2022-03-22T10:36:17.155804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n#grouped = temp_df.groupby(['target'])\n#display(grouped['home'])\nhue_order = ['win','loss','draw']\ntemp_df[\"home_target\"] = 'draw'\nsns.set(font_scale=3)  # crazy big\n\ntemp_df.loc[temp_df['target']=='home','home_target'] = 'win'\ntemp_df.loc[temp_df['target']=='away','home_target'] = 'loss'\n\nt1 = temp_df.loc[temp_df['home_streak_type']=='win']\ngrouped = t1.groupby(['home_streak','home_streak_type'])['home_target'].value_counts(normalize=True)\ngrouped = grouped.mul(100)\ngrouped = grouped.rename('percent').reset_index()\ng = sns.catplot(x=\"home_streak\",y='percent',hue='home_target',kind='bar',hue_order=hue_order,data=grouped,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate depending on win streak  (for home team only)\", fontsize=40)\ng.set_axis_labels(\"Win Streak\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(1)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()\n\nt1 = temp_df.loc[temp_df['home_streak_type']=='loss']\ngrouped = t1.groupby(['home_streak','home_streak_type'])['home_target'].value_counts(normalize=True)\ngrouped = grouped.mul(100)\ngrouped = grouped.rename('percent').reset_index()\ng = sns.catplot(x=\"home_streak\",y='percent',hue='home_target',kind='bar',hue_order=hue_order,data=grouped,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate depending on loss streak  (for home team only)\", fontsize=40)\ng.set_axis_labels(\"Loss Streak\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(1)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()\n\nt1 = temp_df.loc[temp_df['home_streak_type']=='draw']\ngrouped = t1.groupby(['home_streak','home_streak_type'])['home_target'].value_counts(normalize=True)\ngrouped = grouped.mul(100)\ngrouped = grouped.rename('percent').reset_index()\n\ng = sns.catplot(x=\"home_streak\",y='percent',hue='home_target',kind='bar',hue_order=hue_order,data=grouped,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate depending on draw streak (for home team only)\", fontsize=40)\ng.set_axis_labels(\"Draw Streak\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(1)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:36:17.157898Z","iopub.execute_input":"2022-03-22T10:36:17.158133Z","iopub.status.idle":"2022-03-22T10:36:20.141272Z","shell.execute_reply.started":"2022-03-22T10:36:17.158105Z","shell.execute_reply":"2022-03-22T10:36:20.140447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There is a very clear correlation between increase in wins and losses to win streak and loss streak respectively for the home team. Win rate increases from 45% to 75% when win streak increases from 1 to 10. Similarly loss rate increases from 33% to 64% between loss streak of 1 and 10. The correlation between draw rate and draw streaks is not as obvious, though there is a small increase in draw rate for larger draw streaks. Note that there are not as many draw streaks as there are win and loss streaks.","metadata":{}},{"cell_type":"code","source":"hue_order = ['win','loss','draw']\ntemp_df[\"away_target\"] = 'draw'\nsns.set(font_scale=3)  # crazy big\n\ntemp_df.loc[temp_df['target']=='away','away_target'] = 'win'\ntemp_df.loc[temp_df['target']=='home','away_target'] = 'loss'\n\nt1 = temp_df.loc[temp_df['away_streak_type']=='win']\ngrouped = t1.groupby(['away_streak','away_streak_type'])['away_target'].value_counts(normalize=True)\ngrouped = grouped.mul(100)\ngrouped = grouped.rename('percent').reset_index()\ng = sns.catplot(x=\"away_streak\",y='percent',hue='away_target',kind='bar',hue_order=hue_order,data=grouped,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate depending on win streak  (for away team only)\", fontsize=40)\ng.set_axis_labels(\"Win Streak\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(1)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()\n\nt1 = temp_df.loc[temp_df['away_streak_type']=='loss']\ngrouped = t1.groupby(['away_streak','away_streak_type'])['away_target'].value_counts(normalize=True)\ngrouped = grouped.mul(100)\ngrouped = grouped.rename('percent').reset_index()\ng = sns.catplot(x=\"away_streak\",y='percent',hue='away_target',kind='bar',hue_order=hue_order,data=grouped,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate depending on loss streak  (for away team only)\", fontsize=40)\ng.set_axis_labels(\"Loss Streak\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(1)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()\n\nt1 = temp_df.loc[temp_df['away_streak_type']=='draw']\ngrouped = t1.groupby(['away_streak','away_streak_type'])['away_target'].value_counts(normalize=True)\ngrouped = grouped.mul(100)\ngrouped = grouped.rename('percent').reset_index()\n\ng = sns.catplot(x=\"away_streak\",y='percent',hue='away_target',kind='bar',hue_order=hue_order,data=grouped,height=15,aspect=3)\nplt.title(\"Win/loss/draw rate depending on draw streak (for away team only)\", fontsize=40)\ng.set_axis_labels(\"Draw Streak\",\"Game Winner (%)\")\nfor p in g.ax.patches:\n    txt = str(p.get_height().round(1)) + '%'\n    txt_x = p.get_x() \n    txt_y = p.get_height()\n    g.ax.text(txt_x,txt_y,txt)\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:36:20.14239Z","iopub.execute_input":"2022-03-22T10:36:20.14259Z","iopub.status.idle":"2022-03-22T10:36:23.2406Z","shell.execute_reply.started":"2022-03-22T10:36:20.142564Z","shell.execute_reply":"2022-03-22T10:36:23.239683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The same patterns can be seen for the away team when it come to form. There are larger win rates for teams that are on good form while there are larger loss rates for teams on bad form.","metadata":{}},{"cell_type":"markdown","source":"# Points System","metadata":{}},{"cell_type":"code","source":"def add_wins(df):\n    h_t_goal = \"home_team_history_goal_\"\n    h_t_opp_goal = \"home_team_history_opponent_goal_\"\n    a_t_goal = \"away_team_history_goal_\"\n    a_t_opp_goal = \"away_team_history_opponent_goal_\"\n    for i in range(1,11):\n        df[\"home_team_history_win_\" + str(i)] = 'draw'\n        df['away_team_history_win_' + str(i)] = 'draw'\n    def apply_wins(x,idx):\n\n        def check_wins(team_goal,opp_goal):\n            if team_goal > opp_goal:\n                return \"win\"\n            elif team_goal < opp_goal:\n                return \"loss\"\n            elif team_goal == opp_goal:\n                return \"draw\"\n                \n        for i in range(1,11):\n            df.at[idx,\"home_team_history_win_\" + str(i)] = check_wins(x[h_t_goal+str(i)],x[h_t_opp_goal+str(i)])\n            df.at[idx,\"away_team_history_win_\" + str(i)] = check_wins(x[a_t_goal+str(i)],x[a_t_opp_goal+str(i)])\n            \n        #return pd.Series([home_streak,home_streak_type,away_streak,away_streak_type],index=['home_streak','home_streak_type','away_streak','away_streak_type'])\n\n    \n    #df[['home_streak','home_streak_type','away_streak','away_streak_type']] = df.apply(lambda x: apply_streaks(x,x.name), axis=1)\n    df.apply(lambda x: apply_wins(x,x.name), axis=1)\n    return df","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:36:23.242377Z","iopub.execute_input":"2022-03-22T10:36:23.242746Z","iopub.status.idle":"2022-03-22T10:36:23.254783Z","shell.execute_reply.started":"2022-03-22T10:36:23.242697Z","shell.execute_reply":"2022-03-22T10:36:23.253926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def add_points(df):\n    h_t_goal = \"home_team_history_goal_\"\n    h_t_opp_goal = \"home_team_history_opponent_goal_\"\n    a_t_goal = \"away_team_history_goal_\"\n    a_t_opp_goal = \"away_team_history_opponent_goal_\"\n    for i in range(1,11):\n        df[\"home_team_history_point_\" + str(i)] = np.nan\n        df['away_team_history_point_' + str(i)] = np.nan\n    def apply_points(x,idx):\n\n        def check_points(team_goal,opp_goal):\n            if team_goal > opp_goal:\n                return 3\n            elif team_goal < opp_goal:\n                return 0\n            elif team_goal == opp_goal:\n                return 1\n                \n        for i in range(1,11):\n            df.at[idx,\"home_team_history_point_\" + str(i)] = check_points(x[h_t_goal+str(i)],x[h_t_opp_goal+str(i)])\n            df.at[idx,\"away_team_history_point_\" + str(i)] = check_points(x[a_t_goal+str(i)],x[a_t_opp_goal+str(i)])\n            \n        #return pd.Series([home_streak,home_streak_type,away_streak,away_streak_type],index=['home_streak','home_streak_type','away_streak','away_streak_type'])\n\n    \n    #df[['home_streak','home_streak_type','away_streak','away_streak_type']] = df.apply(lambda x: apply_streaks(x,x.name), axis=1)\n    df.apply(lambda x: apply_points(x,x.name), axis=1)\n    return df","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-03-22T10:36:23.255753Z","iopub.execute_input":"2022-03-22T10:36:23.256155Z","iopub.status.idle":"2022-03-22T10:36:23.272953Z","shell.execute_reply.started":"2022-03-22T10:36:23.256124Z","shell.execute_reply":"2022-03-22T10:36:23.272237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"add_points(df)\nadd_wins(df)","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:36:23.274248Z","iopub.execute_input":"2022-03-22T10:36:23.274467Z","iopub.status.idle":"2022-03-22T10:38:15.719304Z","shell.execute_reply.started":"2022-03-22T10:36:23.27444Z","shell.execute_reply":"2022-03-22T10:38:15.718657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cols = []\nfor i in temp_df.columns:\n    if \"point\" in i:\n        cols.append(i)\nprint(cols)\ntemp_df[cols]","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:38:15.720337Z","iopub.execute_input":"2022-03-22T10:38:15.720741Z","iopub.status.idle":"2022-03-22T10:38:15.772403Z","shell.execute_reply.started":"2022-03-22T10:38:15.720707Z","shell.execute_reply":"2022-03-22T10:38:15.771348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cols = []\nfor i in temp_df.columns:\n    if \"point\" in i and \"home\" in i:\n        cols.append(i)\n        \np = \"history_point_\"\ntemp_df = df\ntemp_df['points_last_10'] = df[cols].sum(axis=1)\n\nhue_order = ['draw','loss','win']\ntemp_df[\"alt_target\"] = 'draw'\nsns.set(font_scale=3)  \n\ntemp_df.loc[temp_df['target']=='home','alt_target'] = 'win'\ntemp_df.loc[temp_df['target']=='away','alt_target'] = 'loss'\nax = sns.displot(x='points_last_10',hue='alt_target', element='bars',discrete=True,data=temp_df,height=15,aspect=3,hue_order=hue_order)\nax.set_axis_labels(\"Points\",\"Probability\")\nplt.title(\"Distribution of total points gained in the last 10 games for the game winning/losing/drawing team\")\nplt.show()\nax = sns.displot(x='points_last_10',hue='alt_target', kind=\"kde\",data=temp_df,height=15,aspect=3,hue_order=hue_order)\nax.set_axis_labels(\"Points\",\"Probability\")\nplt.title(\"Distribution of total points gained in the last 10 games for the game winning/losing/drawing team\")\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-03-22T10:38:51.510115Z","iopub.execute_input":"2022-03-22T10:38:51.510396Z","iopub.status.idle":"2022-03-22T10:38:55.144969Z","shell.execute_reply.started":"2022-03-22T10:38:51.510366Z","shell.execute_reply":"2022-03-22T10:38:55.144208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Probability density for the winning team is much higher for teams that have more points gained in the last 10 games. Probability density for low points (0-8 in last 10 games) is noticably higher for the losing teams.","metadata":{}},{"cell_type":"markdown","source":"## Work in progress\n\n- Rest Days\n- Goal Diff\n- ELO\n- Points per match","metadata":{}}]}