{"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":"markdown","source":"The following code use the idea from Claus Herther's blogpost on Bayesian modelling of field goal https://calogica.com/pymc3/python/2020/01/10/nfl-field-goals-bayes.html and apply to tracking data of field goals. The following code would be a brief outline of model only and more details are in the blogpost.","metadata":{}},{"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)\nimport pymc3 as pm\nimport arviz as az\n\npd.options.display.max_columns = 999\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-10-01T05:39:38.044805Z","iopub.execute_input":"2021-10-01T05:39:38.04508Z","iopub.status.idle":"2021-10-01T05:39:42.663711Z","shell.execute_reply.started":"2021-10-01T05:39:38.045051Z","shell.execute_reply":"2021-10-01T05:39:42.662866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"play_data = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2022/plays.csv')","metadata":{"execution":{"iopub.status.busy":"2021-10-01T05:39:42.665195Z","iopub.execute_input":"2021-10-01T05:39:42.665381Z","iopub.status.idle":"2021-10-01T05:39:42.821132Z","shell.execute_reply.started":"2021-10-01T05:39:42.665358Z","shell.execute_reply":"2021-10-01T05:39:42.820476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"field_goal_data = play_data[play_data.specialTeamsPlayType == 'Field Goal'][['gameId','playId','absoluteYardlineNumber','specialTeamsResult']]","metadata":{"execution":{"iopub.status.busy":"2021-10-01T05:39:42.877716Z","iopub.execute_input":"2021-10-01T05:39:42.877953Z","iopub.status.idle":"2021-10-01T05:39:42.892656Z","shell.execute_reply.started":"2021-10-01T05:39:42.877924Z","shell.execute_reply":"2021-10-01T05:39:42.89195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pff_data = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2022/PFFScoutingData.csv')","metadata":{"execution":{"iopub.status.busy":"2021-10-01T05:39:42.94849Z","iopub.execute_input":"2021-10-01T05:39:42.948782Z","iopub.status.idle":"2021-10-01T05:39:43.039585Z","shell.execute_reply.started":"2021-10-01T05:39:42.948756Z","shell.execute_reply":"2021-10-01T05:39:43.03884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_data = []\n\nfor year in range(2018,2021):\n    data = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2022/tracking'+str(year) + '.csv')\n    data = data[data.event == 'field_goal_attempt']\n    tracking_data.append(data)\ntracking_data = pd.concat(tracking_data)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:17:52.542879Z","iopub.execute_input":"2021-10-01T07:17:52.543599Z","iopub.status.idle":"2021-10-01T07:19:56.892754Z","shell.execute_reply.started":"2021-10-01T07:17:52.543548Z","shell.execute_reply":"2021-10-01T07:19:56.89184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del data","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:56.894953Z","iopub.execute_input":"2021-10-01T07:19:56.895583Z","iopub.status.idle":"2021-10-01T07:19:56.901016Z","shell.execute_reply.started":"2021-10-01T07:19:56.895537Z","shell.execute_reply":"2021-10-01T07:19:56.900196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_data = pd.merge(tracking_data,field_goal_data)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:56.947336Z","iopub.execute_input":"2021-10-01T07:19:56.947702Z","iopub.status.idle":"2021-10-01T07:19:56.97456Z","shell.execute_reply.started":"2021-10-01T07:19:56.947671Z","shell.execute_reply":"2021-10-01T07:19:56.973886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tracking_data.loc[tracking_data.playDirection == 'left','x'] = 120-tracking_data['x']\ntracking_data.loc[tracking_data.playDirection == 'left','y'] = 53.33-tracking_data['y']","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:56.975688Z","iopub.execute_input":"2021-10-01T07:19:56.976053Z","iopub.status.idle":"2021-10-01T07:19:57.009247Z","shell.execute_reply.started":"2021-10-01T07:19:56.976007Z","shell.execute_reply":"2021-10-01T07:19:57.008353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"field_goal_ball_df = tracking_data[tracking_data.team == 'football']","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.010624Z","iopub.execute_input":"2021-10-01T07:19:57.010849Z","iopub.status.idle":"2021-10-01T07:19:57.04091Z","shell.execute_reply.started":"2021-10-01T07:19:57.010824Z","shell.execute_reply":"2021-10-01T07:19:57.040217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To find the angle between the ball and two side of goalpost the formula is given by $\\theta=\\arccos(\\frac{\\vec{AB}\\cdot\\vec{BC}}{\\vec{|AB|}\\vec{|BC|}})$ where AB and BC are two line from goalpost to ball. \n\nNFL goalpost width is 18.5 feet (6 1/6 yards) and the width of whole field is 160 feet (53 1/3 yards), which makes the goalpost coordinate be $26\\frac{1}{6} \\pm 3\\frac{1}{12}$ yards","metadata":{}},{"cell_type":"code","source":"ba = np.array(np.array([120,23.583])-field_goal_ball_df[['x','y']])\nbc = np.array(np.array([120,29.75])-field_goal_ball_df[['x','y']])\n\nfield_goal_ball_df['angle'] =  np.degrees(np.arccos(np.array([np.dot(a,b) for a,b in zip(ba,bc)])/(np.linalg.norm(ba,axis=1)  * np.linalg.norm(bc,axis=1) )))","metadata":{"execution":{"iopub.status.busy":"2021-10-01T14:07:13.451057Z","iopub.execute_input":"2021-10-01T14:07:13.452046Z","iopub.status.idle":"2021-10-01T14:07:13.585204Z","shell.execute_reply.started":"2021-10-01T14:07:13.451903Z","shell.execute_reply":"2021-10-01T14:07:13.58398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Similarly instead of using yardsline mark for field goal distance in traditional way, here field goal distance is measured from ball to center of goalpost","metadata":{}},{"cell_type":"code","source":"field_goal_ball_df['fg_dist'] = ((field_goal_ball_df['x'] - 120)**2 + (field_goal_ball_df['y'] - 26.33)**2)**0.5","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.074982Z","iopub.execute_input":"2021-10-01T07:19:57.07559Z","iopub.status.idle":"2021-10-01T07:19:57.085003Z","shell.execute_reply.started":"2021-10-01T07:19:57.075541Z","shell.execute_reply":"2021-10-01T07:19:57.083938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"field_goal_ball_df = field_goal_ball_df[field_goal_ball_df.fg_dist <= 70]","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.089013Z","iopub.execute_input":"2021-10-01T07:19:57.089291Z","iopub.status.idle":"2021-10-01T07:19:57.098302Z","shell.execute_reply.started":"2021-10-01T07:19:57.089261Z","shell.execute_reply":"2021-10-01T07:19:57.097628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"field_goal_ball_df['fg_make'] = np.array(field_goal_ball_df[\"specialTeamsResult\"] == 'Kick Attempt Good').astype(int)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.099219Z","iopub.execute_input":"2021-10-01T07:19:57.099933Z","iopub.status.idle":"2021-10-01T07:19:57.109961Z","shell.execute_reply.started":"2021-10-01T07:19:57.099901Z","shell.execute_reply":"2021-10-01T07:19:57.109343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y = field_goal_ball_df['fg_make']\nn = np.ones_like(field_goal_ball_df['fg_make'])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.157893Z","iopub.execute_input":"2021-10-01T07:19:57.158135Z","iopub.status.idle":"2021-10-01T07:19:57.162493Z","shell.execute_reply.started":"2021-10-01T07:19:57.158107Z","shell.execute_reply":"2021-10-01T07:19:57.161606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_kick_data(df, ax=None):\n    \n    if ax is None:\n        _, ax = plt.subplots(1, 1, figsize=(12,8))\n    sns.regplot(x=\"fg_dist\", y=\"fg_make\", data=df, label=\"observed\", ax=ax, logistic=True);\n    \n    vals = ax.get_yticks()\n    _ = ax.set_yticklabels(['{:,.1%}'.format(x) for x in vals])\n    ax.set_xlabel(\"Yards Kicked\")\n    ax.set_ylabel(\"Field Goal Success %\")\n    _ = ax.set_title(\"Field Goal % by Yards Kicked\")\n    \n    return ax","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.16363Z","iopub.execute_input":"2021-10-01T07:19:57.163837Z","iopub.status.idle":"2021-10-01T07:19:57.175314Z","shell.execute_reply.started":"2021-10-01T07:19:57.163813Z","shell.execute_reply":"2021-10-01T07:19:57.174515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_ = plot_kick_data(field_goal_ball_df)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:19:57.17668Z","iopub.execute_input":"2021-10-01T07:19:57.17753Z","iopub.status.idle":"2021-10-01T07:20:05.194423Z","shell.execute_reply.started":"2021-10-01T07:19:57.177483Z","shell.execute_reply":"2021-10-01T07:20:05.193571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As stated in the blog post, the specification of model is as followed:\n\n$\\large \\alpha\\sim Normal(0,1)$\n\n$\\large \\beta\\sim Normal(0,1)$\n\n$\\large z = a + b \\ast X_i$\n\n$\\large p_i = sigmoid(z)$\n\n$\\large y\\sim Binomial(n, p_i)$","metadata":{}},{"cell_type":"markdown","source":"Three models are considered: field goal distance only, distance & angle and interaction between distance and angle.","metadata":{}},{"cell_type":"code","source":"X = np.array(field_goal_ball_df[\"fg_dist\"])\n\nwith pm.Model() as model_logit_yards:\n    \n    α = pm.Normal(\"α\", mu=0, sd=1)\n    β = pm.Normal(\"β\", mu=0, sd=1)\n\n    z = α + β * X\n    p = pm.Deterministic(\"p\", pm.math.invlogit(z))\n\n    y_obs = pm.Binomial(\"y_obs\",n=n, p=p, observed=y)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:05.275227Z","iopub.execute_input":"2021-10-01T07:20:05.275477Z","iopub.status.idle":"2021-10-01T07:20:05.671283Z","shell.execute_reply.started":"2021-10-01T07:20:05.275447Z","shell.execute_reply":"2021-10-01T07:20:05.670413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pm.model_to_graphviz(model_logit_yards)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:05.67261Z","iopub.execute_input":"2021-10-01T07:20:05.672829Z","iopub.status.idle":"2021-10-01T07:20:05.814297Z","shell.execute_reply.started":"2021-10-01T07:20:05.672801Z","shell.execute_reply":"2021-10-01T07:20:05.813212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with model_logit_yards:\n    trace_logit_yards = pm.sample(2000, tune=2000, chains=2, target_accept=0.95, return_inferencedata=True)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:05.815985Z","iopub.execute_input":"2021-10-01T07:20:05.816334Z","iopub.status.idle":"2021-10-01T07:20:56.664237Z","shell.execute_reply.started":"2021-10-01T07:20:05.816295Z","shell.execute_reply":"2021-10-01T07:20:56.663499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"az.summary(trace_logit_yards,var_names=[\"α\",\"β\"])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:56.665503Z","iopub.execute_input":"2021-10-01T07:20:56.666148Z","iopub.status.idle":"2021-10-01T07:20:56.715045Z","shell.execute_reply.started":"2021-10-01T07:20:56.666106Z","shell.execute_reply":"2021-10-01T07:20:56.714276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"az.plot_trace(trace_logit_yards,var_names=[\"α\",\"β\"])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:56.716184Z","iopub.execute_input":"2021-10-01T07:20:56.716423Z","iopub.status.idle":"2021-10-01T07:20:57.567004Z","shell.execute_reply.started":"2021-10-01T07:20:56.716395Z","shell.execute_reply":"2021-10-01T07:20:57.566114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\ndef plot_probs_yard(df, probas_posterior, model_name, ax=None):\n    \n    if ax is None:\n        _, ax = plt.subplots(1, 1, figsize=(12,8))\n    \n    az.plot_hdi(x=np.array(field_goal_ball_df[\"fg_dist\"]), y=probas_posterior, hdi_prob=.95, ax=ax, fill_kwargs={'alpha': .2})\n    \n    _ = plot_kick_data(df, ax)\n    ax.set_title(f\"{ax.get_title()} - {model_name}\") ;\n    \n    return ax\n\n","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.568454Z","iopub.execute_input":"2021-10-01T07:20:57.568884Z","iopub.status.idle":"2021-10-01T07:20:57.577342Z","shell.execute_reply.started":"2021-10-01T07:20:57.568842Z","shell.execute_reply":"2021-10-01T07:20:57.576362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_probs_yard(field_goal_ball_df, trace_logit_yards.posterior[\"p\"], \"Logistic Model: Distance\")","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.57856Z","iopub.execute_input":"2021-10-01T07:20:57.578865Z","iopub.status.idle":"2021-10-01T07:20:57.902535Z","shell.execute_reply.started":"2021-10-01T07:20:57.578831Z","shell.execute_reply":"2021-10-01T07:20:57.89935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X = np.array(field_goal_ball_df[[\"fg_dist\",'angle']])\n","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.903567Z","iopub.status.idle":"2021-10-01T07:20:57.903926Z","shell.execute_reply.started":"2021-10-01T07:20:57.903739Z","shell.execute_reply":"2021-10-01T07:20:57.903762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with pm.Model() as model_logit_yards_angle:\n\n    α = pm.Normal(\"α\", mu=0, sd=.1)\n    β = pm.Normal(\"β\", mu=0, sd=.1, shape=X.shape[1])\n\n    z = α + pm.math.dot(X, β)\n\n    p = pm.Deterministic(\"p\", pm.math.invlogit(z))\n\n    y_obs = pm.Binomial(\"y_obs\", n=n, p=p, observed=y)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.905563Z","iopub.status.idle":"2021-10-01T07:20:57.906547Z","shell.execute_reply.started":"2021-10-01T07:20:57.906222Z","shell.execute_reply":"2021-10-01T07:20:57.906253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pm.model_to_graphviz(model_logit_yards_angle)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.907747Z","iopub.status.idle":"2021-10-01T07:20:57.908688Z","shell.execute_reply.started":"2021-10-01T07:20:57.908382Z","shell.execute_reply":"2021-10-01T07:20:57.908413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with model_logit_yards_angle:\n    trace_logit_yards_angle = pm.sample(2000, tune=2000, chains=2, target_accept=0.95, return_inferencedata=True)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.910285Z","iopub.status.idle":"2021-10-01T07:20:57.910827Z","shell.execute_reply.started":"2021-10-01T07:20:57.910558Z","shell.execute_reply":"2021-10-01T07:20:57.910583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"az.summary(trace_logit_yards_angle,var_names=[\"α\",\"β\"])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.912301Z","iopub.status.idle":"2021-10-01T07:20:57.912802Z","shell.execute_reply.started":"2021-10-01T07:20:57.912542Z","shell.execute_reply":"2021-10-01T07:20:57.912566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"az.plot_trace(trace_logit_yards_angle,var_names=[\"α\",\"β\"])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.914492Z","iopub.status.idle":"2021-10-01T07:20:57.915064Z","shell.execute_reply.started":"2021-10-01T07:20:57.914719Z","shell.execute_reply":"2021-10-01T07:20:57.914744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_probs_yard(field_goal_ball_df, trace_logit_yards_angle.posterior[\"p\"], \"Logistic Model: Yards + Angle\")","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.918169Z","iopub.status.idle":"2021-10-01T07:20:57.91869Z","shell.execute_reply.started":"2021-10-01T07:20:57.918396Z","shell.execute_reply":"2021-10-01T07:20:57.918421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"field_goal_ball_df[\"fg_dist_angle\"] = field_goal_ball_df[\"fg_dist\"] * field_goal_ball_df[\"angle\"]\nX = field_goal_ball_df[[\"fg_dist\",'angle',\"fg_dist_angle\"]]\n","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.920273Z","iopub.status.idle":"2021-10-01T07:20:57.920779Z","shell.execute_reply.started":"2021-10-01T07:20:57.920521Z","shell.execute_reply":"2021-10-01T07:20:57.920546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with pm.Model() as model_logit_yards_angle_interactions:\n\n    α = pm.Normal(\"α\", mu=0, sd=.1)\n    β = pm.Normal(\"β\", mu=0, sd=.1, shape=X.shape[1])\n\n    z = α + pm.math.dot(X, β)\n\n    p = pm.Deterministic(\"p\", pm.math.invlogit(z))\n\n    y_obs = pm.Binomial(\"y_obs\", n=n, p=p, observed=y)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.922123Z","iopub.status.idle":"2021-10-01T07:20:57.922444Z","shell.execute_reply.started":"2021-10-01T07:20:57.92228Z","shell.execute_reply":"2021-10-01T07:20:57.922296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pm.model_to_graphviz(model_logit_yards_angle_interactions)","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.923292Z","iopub.status.idle":"2021-10-01T07:20:57.923627Z","shell.execute_reply.started":"2021-10-01T07:20:57.923463Z","shell.execute_reply":"2021-10-01T07:20:57.923478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with model_logit_yards_angle_interactions:\n    trace_logit_yards_angle_interactions = pm.sample(2000, tune=2000, chains=2, target_accept=0.95, return_inferencedata=True)\n","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.924617Z","iopub.status.idle":"2021-10-01T07:20:57.924924Z","shell.execute_reply.started":"2021-10-01T07:20:57.924759Z","shell.execute_reply":"2021-10-01T07:20:57.924773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"az.summary(trace_logit_yards_angle_interactions,var_names=[\"α\",\"β\"])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.925736Z","iopub.status.idle":"2021-10-01T07:20:57.926126Z","shell.execute_reply.started":"2021-10-01T07:20:57.925901Z","shell.execute_reply":"2021-10-01T07:20:57.925916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"az.plot_trace(trace_logit_yards_angle_interactions,var_names=[\"α\",\"β\"])","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.927181Z","iopub.status.idle":"2021-10-01T07:20:57.92749Z","shell.execute_reply.started":"2021-10-01T07:20:57.927328Z","shell.execute_reply":"2021-10-01T07:20:57.927343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_probs_yard(field_goal_ball_df, trace_logit_yards_angle_interactions.posterior[\"p\"], \"Logistic Model: Yards + Angle + Yards:Angle\")","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.928812Z","iopub.status.idle":"2021-10-01T07:20:57.929161Z","shell.execute_reply.started":"2021-10-01T07:20:57.928963Z","shell.execute_reply":"2021-10-01T07:20:57.928978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"compare_dict = {\"Logistic Model: Distance\": trace_logit_yards, \n                \"Logistic Model: Distance + Angle\": trace_logit_yards_angle,\n                \"Logistic Model: Distance + Angle + Distance*Angle)\": trace_logit_yards_angle_interactions\n\n               }\ndf_compare = az.compare(compare_dict, ic=\"loo\")\ndf_compare","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.930095Z","iopub.status.idle":"2021-10-01T07:20:57.93045Z","shell.execute_reply.started":"2021-10-01T07:20:57.93028Z","shell.execute_reply":"2021-10-01T07:20:57.930296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_, ax = plt.subplots(1, 1, figsize=(10, 5))\naz.plot_compare(df_compare, ax=ax);","metadata":{"execution":{"iopub.status.busy":"2021-10-01T07:20:57.93134Z","iopub.status.idle":"2021-10-01T07:20:57.931637Z","shell.execute_reply.started":"2021-10-01T07:20:57.931479Z","shell.execute_reply":"2021-10-01T07:20:57.931494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"After using real tracking data for modelling, all three models are not significantly different from others and so the simplist model with field goal distance only could've be considered for further modelling.","metadata":{}}]}