{"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\n\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nfrom IPython.display import Image","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-06T22:28:05.378777Z","iopub.execute_input":"2022-01-06T22:28:05.379067Z","iopub.status.idle":"2022-01-06T22:28:05.390667Z","shell.execute_reply.started":"2022-01-06T22:28:05.379032Z","shell.execute_reply":"2022-01-06T22:28:05.390102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read csv files into pandas dataframea\nfile_name = \"/kaggle/input/punt-plays-at-ball-snap/bdb2022_analysis_dataset_20220105.csv\"\ndf = pd.read_csv(file_name, index_col=None) \nplays_df = pd.read_csv('/kaggle/input/nfl-big-data-bowl-2022/plays.csv', index_col=None)","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:45.80206Z","iopub.execute_input":"2022-01-06T20:54:45.802524Z","iopub.status.idle":"2022-01-06T20:54:46.148106Z","shell.execute_reply.started":"2022-01-06T20:54:45.802478Z","shell.execute_reply":"2022-01-06T20:54:46.147281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_horizontal_field(show_line_numbers=True,\n                            show_line_of_scrimmage=False,\n                            line_of_scrimmage=60,\n                            figsize=(12, 6.33)):\n\n    rect = patches.Rectangle((0, 0), 120, 53.3, linewidth=0.1,\n                             edgecolor='r', facecolor='green', zorder=0)\n\n    fig, ax = plt.subplots(1, figsize=figsize)\n    ax.add_patch(rect)\n\n    plt.plot([10, 10, 10, 20, 20, 30, 30, 40, 40, 50, 50, 60, 60, 70, 70, 80,\n              80, 90, 90, 100, 100, 110, 110, 120, 0, 0, 120, 120],\n             [0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3,\n              53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 53.3, 0, 0, 53.3],\n             color='white')\n    \n    # endzones\n    ez1 = patches.Rectangle((0, 0), 10, 53.3,\n                            linewidth=0.1,\n                            edgecolor='r',\n                            facecolor='blue',\n                            alpha=0.2,\n                            zorder=0)\n    ez2 = patches.Rectangle((110, 0), 120, 53.3,\n                            linewidth=0.1,\n                            edgecolor='r',\n                            facecolor='blue', \n                            alpha=0.2,\n                            zorder=0)\n    ax.add_patch(ez1)\n    ax.add_patch(ez2)\n    \n    plt.xlim(0, 120)\n    plt.ylim(0, 53.3)\n    plt.axis('off')\n    if show_line_numbers:\n        for x in range(20, 110, 10):\n            numb = x\n            if x > 50:\n                numb = 120 - x\n            plt.text(x, 3, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,\n                     color='white')\n            plt.text(x - 0.95, 53.3 - 5, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,\n                     color='white', rotation=180)\n\n    hash_range = range(11, 110)\n    for x in hash_range:\n        ax.plot([x, x], [0.4, 0.7], color='white')\n        ax.plot([x, x], [53.0, 52.5], color='white')\n        ax.plot([x, x], [22.91, 23.57], color='white')\n        ax.plot([x, x], [29.73, 30.39], color='white')\n\n    if show_line_of_scrimmage :\n        line_of_scrimmage = line_of_scrimmage\n        plt.plot([line_of_scrimmage, line_of_scrimmage], [0, 53.3], color='blue')\n    \n    return fig, ax","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.149632Z","iopub.execute_input":"2022-01-06T20:54:46.149903Z","iopub.status.idle":"2022-01-06T20:54:46.162514Z","shell.execute_reply.started":"2022-01-06T20:54:46.149863Z","shell.execute_reply":"2022-01-06T20:54:46.161681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_vertical_field(show_line_numbers=True,\n                          show_line_of_scrimmage=False,\n                          line_of_scrimmage=60,\n                          figsize=(6.33, 12)):\n\n    rect = patches.Rectangle((0, 0),  53.3, 120, linewidth=0.1,\n                             edgecolor='r', facecolor='green', zorder=0)\n\n    fig, ax = plt.subplots(1, figsize=figsize)\n    ax.add_patch(rect)\n\n    plt.plot([0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, \n              53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 53.3, 0, 0, 53.3],\n              [10, 10, 10, 20, 20, 30, 30, 40, 40, 50, 50, 60, 60, 70, 70, 80, \n              80, 90, 90, 100, 100, 110, 110, 120, 0, 0, 120, 120],\n              color='white')\n    \n    # endzones\n    ez1 = patches.Rectangle((0, 0), 53.3, 10,\n                            linewidth=0.1,\n                            edgecolor='r',\n                            facecolor='blue',\n                            alpha=0.2,\n                            zorder=0)\n    ez2 = patches.Rectangle((0, 110), 53.3, 120,\n                            linewidth=0.1,\n                            edgecolor='r',\n                            facecolor='blue', \n                            alpha=0.2,\n                            zorder=0)\n    ax.add_patch(ez1)\n    ax.add_patch(ez2)\n    \n    plt.xlim(0, 58.3)\n    plt.ylim(0, 120)\n    plt.axis('off')\n    if show_line_numbers:\n        for y in range(20, 110, 10):\n            numb = y\n            if y > 50:\n                numb = 120 - y\n            plt.text(4, y - 2, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,\n                     color='white', rotation=270)\n            plt.text(53.3 - 5, y - 0.95, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,\n                     color='white', rotation=90)\n\n    hash_range = range(11, 110)\n    for y in hash_range:\n        ax.plot([0.4, 0.7], [y, y], color='white')\n        ax.plot([53.0, 52.5], [y, y], color='white')\n        ax.plot([22.91, 23.57], [y, y], color='white')\n        ax.plot([29.73, 30.39], [y, y], color='white')\n\n    if show_line_of_scrimmage :\n        line_of_scrimmage = line_of_scrimmage\n        plt.plot([0, 53.3], [line_of_scrimmage, line_of_scrimmage], color='blue')\n    \n    return fig, ax","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.164331Z","iopub.execute_input":"2022-01-06T20:54:46.164756Z","iopub.status.idle":"2022-01-06T20:54:46.17873Z","shell.execute_reply.started":"2022-01-06T20:54:46.164715Z","shell.execute_reply":"2022-01-06T20:54:46.178155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Image(\"../input/nfl-field/nfl_field.png\")","metadata":{"execution":{"iopub.status.busy":"2022-01-06T22:30:06.741682Z","iopub.execute_input":"2022-01-06T22:30:06.741932Z","iopub.status.idle":"2022-01-06T22:30:06.84856Z","shell.execute_reply.started":"2022-01-06T22:30:06.741907Z","shell.execute_reply":"2022-01-06T22:30:06.847266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <font color=blue>Normalize Play Direction</font>\n<hr style=\"border:1px solid blue\" />","metadata":{}},{"cell_type":"markdown","source":"### Example Left-to-Right Play (gameId 2019092211, playId 218)\nSee https://www.youtube.com/watch?v=-h34qUml52c","metadata":{"execution":{"iopub.status.busy":"2022-01-06T02:17:18.726133Z","iopub.execute_input":"2022-01-06T02:17:18.727084Z","iopub.status.idle":"2022-01-06T02:17:18.731575Z","shell.execute_reply.started":"2022-01-06T02:17:18.727042Z","shell.execute_reply":"2022-01-06T02:17:18.730381Z"}}},{"cell_type":"code","source":"ayl_hf_nonNDOP = plays_df.query('gameId==2019092211 and playId==218')['absoluteYardlineNumber']","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.179814Z","iopub.execute_input":"2022-01-06T20:54:46.180028Z","iopub.status.idle":"2022-01-06T20:54:46.204147Z","shell.execute_reply.started":"2022-01-06T20:54:46.179996Z","shell.execute_reply":"2022-01-06T20:54:46.203362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_left_to_right_play = df.query('gameId==2019092211 and playId==218')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.205424Z","iopub.execute_input":"2022-01-06T20:54:46.206085Z","iopub.status.idle":"2022-01-06T20:54:46.214882Z","shell.execute_reply.started":"2022-01-06T20:54:46.206057Z","shell.execute_reply":"2022-01-06T20:54:46.214109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create horizontal field showing line of scrimmage\nfig, ax = create_horizontal_field(show_line_of_scrimmage=True, \n                                  line_of_scrimmage=ayl_hf_nonNDOP)\n\n# plot positions of offensive players\ndf_left_to_right_play. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_hf_nonNDOP', \n         y='y_hf_nonNDOP',\n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# # plot positions of defensive players\ndf_left_to_right_play. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_hf_nonNDOP', \n         y='y_hf_nonNDOP',\n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_left_to_right_play. \\\n    query(\"team=='football' & event=='ball_snap'\"). \\\n    plot(x='x_hf_nonNDOP', \n         y='y_hf_nonNDOP',\n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nPlay of Direction Not Normalized\ngameId 2019092211, playId 218; left-to-right play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.216043Z","iopub.execute_input":"2022-01-06T20:54:46.216811Z","iopub.status.idle":"2022-01-06T20:54:46.962874Z","shell.execute_reply.started":"2022-01-06T20:54:46.216781Z","shell.execute_reply":"2022-01-06T20:54:46.962044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Example Right-to-Left Play (gameId 2018121610, playId 1339)\nSee https://www.youtube.com/watch?v=BQbs7gpfkcI","metadata":{}},{"cell_type":"code","source":"ayl_hf_nonNDOP = plays_df.query('gameId==2018121610 and playId==1339')['absoluteYardlineNumber']","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.964371Z","iopub.execute_input":"2022-01-06T20:54:46.964824Z","iopub.status.idle":"2022-01-06T20:54:46.975041Z","shell.execute_reply.started":"2022-01-06T20:54:46.964782Z","shell.execute_reply":"2022-01-06T20:54:46.974372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_right_to_left_play = df.query('gameId==2018121610 and playId==1339')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.976739Z","iopub.execute_input":"2022-01-06T20:54:46.97727Z","iopub.status.idle":"2022-01-06T20:54:46.98682Z","shell.execute_reply.started":"2022-01-06T20:54:46.977198Z","shell.execute_reply":"2022-01-06T20:54:46.986222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create horizontal field showing line of scrimmage\nfig, ax = create_horizontal_field(show_line_of_scrimmage=True, \n                                  line_of_scrimmage=ayl_hf_nonNDOP)\n\n# plot positions of offensive players\ndf_right_to_left_play. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_hf_nonNDOP', \n         y='y_hf_nonNDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players\ndf_right_to_left_play. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_hf_nonNDOP', \n         y='y_hf_nonNDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_right_to_left_play. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_hf_nonNDOP', \n         y='y_hf_nonNDOP', \n         zorder=1, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nPlay of Direction Not Normalized\ngameId 2018121610, playId 1339:  right-to-left play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:46.988779Z","iopub.execute_input":"2022-01-06T20:54:46.989371Z","iopub.status.idle":"2022-01-06T20:54:47.588709Z","shell.execute_reply.started":"2022-01-06T20:54:46.989342Z","shell.execute_reply":"2022-01-06T20:54:47.587927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Example Right-to-Left Play (gameId 2018121610, playId 1339) Transformed to a Left-to-Right Play\nThis is the same play shown in the plot above, but now we're going to change the direction of play by tranforming the x-y coordinates of the players, football, and line of scrimmage.  You can think of this as simply rotating the plot shown above 180 degrees.\n\nSee https://www.youtube.com/watch?v=BQbs7gpfkcI","metadata":{}},{"cell_type":"code","source":"ayl_hf_NDOP = 120 - plays_df.query('gameId==2018121610 and playId==1339')['absoluteYardlineNumber']","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:47.589838Z","iopub.execute_input":"2022-01-06T20:54:47.590055Z","iopub.status.idle":"2022-01-06T20:54:47.598457Z","shell.execute_reply.started":"2022-01-06T20:54:47.590029Z","shell.execute_reply":"2022-01-06T20:54:47.597811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_rightToLeftPlay_transformedTo_leftToRightPlay = df.query('gameId==2018121610 and playId==1339')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:47.599798Z","iopub.execute_input":"2022-01-06T20:54:47.600135Z","iopub.status.idle":"2022-01-06T20:54:47.611582Z","shell.execute_reply.started":"2022-01-06T20:54:47.600077Z","shell.execute_reply":"2022-01-06T20:54:47.610929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create horizontal field showing line of scrimmage\nfig, ax = create_horizontal_field(show_line_of_scrimmage=True, \n                                  line_of_scrimmage=ayl_hf_NDOP)\n\n# plot positions of offensive players\ndf_rightToLeftPlay_transformedTo_leftToRightPlay. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_hf_NDOP', \n         y='y_hf_NDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players\ndf_rightToLeftPlay_transformedTo_leftToRightPlay. \\\n    query(\"team=='home' & event=='ball_snap'\"). \\\n    plot(x='x_hf_NDOP', \n         y='y_hf_NDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_rightToLeftPlay_transformedTo_leftToRightPlay. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_hf_NDOP', \n         y='y_hf_NDOP', \n         zorder=1, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nPlay of Direction Normalized\ngameId 2018121610, playId 1339:  right-to-left play transformed to a left-to-right play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:47.612685Z","iopub.execute_input":"2022-01-06T20:54:47.612903Z","iopub.status.idle":"2022-01-06T20:54:48.33744Z","shell.execute_reply.started":"2022-01-06T20:54:47.612872Z","shell.execute_reply":"2022-01-06T20:54:48.33665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <font color=blue>Transform X-Y Coordinates for Vertically Transposed Football Field</font>\n<hr style=\"border:1px solid blue\" />","metadata":{}},{"cell_type":"markdown","source":"### Example Left-to-Right Play (gameId 2019092211, playId 218) on Vertical Field","metadata":{}},{"cell_type":"code","source":" absolute_yardline_number = plays_df.query('gameId==2019092211 and playId==218')['absoluteYardlineNumber']","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:48.338798Z","iopub.execute_input":"2022-01-06T20:54:48.339257Z","iopub.status.idle":"2022-01-06T20:54:48.347664Z","shell.execute_reply.started":"2022-01-06T20:54:48.339214Z","shell.execute_reply":"2022-01-06T20:54:48.347045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_lefToRightPlay_verticalField = df.query('gameId==2019092211 and playId==218')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:48.34868Z","iopub.execute_input":"2022-01-06T20:54:48.348933Z","iopub.status.idle":"2022-01-06T20:54:48.361034Z","shell.execute_reply.started":"2022-01-06T20:54:48.348894Z","shell.execute_reply":"2022-01-06T20:54:48.360315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create vertical field showing line of scrimmage\nfig, ax = create_vertical_field(show_line_of_scrimmage=True, \n                                line_of_scrimmage=absolute_yardline_number)\n\n# plot positions of offensive players\ndf_lefToRightPlay_verticalField. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_vf_NDOP', \n         y='y_vf_NDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players\ndf_lefToRightPlay_verticalField. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_vf_NDOP', \n         y='y_vf_NDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_lefToRightPlay_verticalField. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_vf_NDOP', \n         y='y_vf_NDOP', \n         zorder=5, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nVertical Field\nPlay of Direction Normalized\ngameId 2019092211, playId 218; left-to-right play now shown as a bottom-to-top play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:48.362069Z","iopub.execute_input":"2022-01-06T20:54:48.362365Z","iopub.status.idle":"2022-01-06T20:54:48.977788Z","shell.execute_reply.started":"2022-01-06T20:54:48.362324Z","shell.execute_reply":"2022-01-06T20:54:48.977003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Example Right-to-Left Play (gameId 2018121610, playId 1339) on Vertical Field","metadata":{}},{"cell_type":"code","source":"ayl_vf_NDOP = 120 - plays_df.query('gameId==2018121610 and playId==1339')['absoluteYardlineNumber']","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:48.979041Z","iopub.execute_input":"2022-01-06T20:54:48.979298Z","iopub.status.idle":"2022-01-06T20:54:48.987864Z","shell.execute_reply.started":"2022-01-06T20:54:48.979268Z","shell.execute_reply":"2022-01-06T20:54:48.987059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_RightToLeftPlay_verticalField = df.query('gameId==2018121610 and playId==1339')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:48.988924Z","iopub.execute_input":"2022-01-06T20:54:48.989171Z","iopub.status.idle":"2022-01-06T20:54:49.001298Z","shell.execute_reply.started":"2022-01-06T20:54:48.989143Z","shell.execute_reply":"2022-01-06T20:54:49.000225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create vertical field showing line of scrimmage\nfig, ax = create_vertical_field(show_line_of_scrimmage=True, \n                                line_of_scrimmage=ayl_vf_NDOP)\n\n# plot positions of offensive players\ndf_RightToLeftPlay_verticalField. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_vf_NDOP', \n         y='y_vf_NDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players\ndf_RightToLeftPlay_verticalField. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_vf_NDOP', \n         y='y_vf_NDOP', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_RightToLeftPlay_verticalField. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_vf_NDOP', \n         y='y_vf_NDOP', \n         zorder=5, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nVertical Field\nPlay of Direction Normalized\ngameId 2018121610, playId 1339:  right-to-left play now shown as a bottom-to-top play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:49.002421Z","iopub.execute_input":"2022-01-06T20:54:49.003214Z","iopub.status.idle":"2022-01-06T20:54:49.759905Z","shell.execute_reply.started":"2022-01-06T20:54:49.003173Z","shell.execute_reply":"2022-01-06T20:54:49.759273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# <font color=blue>Normalize Line of Scrimmage to Show Multiple Plays on Vertical Field with Single Directon of Play</font>\n<hr style=\"border:1px solid blue\" />\nIn order to show multiple plays on a vertical field we need to normalize the line of scrimmage for each play.  \n\nTo do this we will calculate the offset of each player's (and the football's) y-coordinate from each play's line of scrimmage and then recalulate the y-coordinates to be relative to a line of scrimmage that is always at the 50-yard line.","metadata":{}},{"cell_type":"markdown","source":"### Game 2019092211, Play 218 (left-to-right play)","metadata":{}},{"cell_type":"code","source":"df_p218 = df.query('gameId==2019092211 and playId==218')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T20:54:49.760771Z","iopub.execute_input":"2022-01-06T20:54:49.761437Z","iopub.status.idle":"2022-01-06T20:54:49.769033Z","shell.execute_reply.started":"2022-01-06T20:54:49.761401Z","shell.execute_reply":"2022-01-06T20:54:49.768291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# each record in the dataframe has an ayl_vf_NDOP_losNormalized value, which is the \n# same for all records; therefore, simply get the value from the first record\nlos = df_p218['ayl_vf_NDOP_losNormalized'][:1]\n\n# create vertical field showing normalized line of scrimmage\nfig, ax = create_vertical_field(show_line_of_scrimmage=True, line_of_scrimmage=los)\n\n# plot positions of offensive players\ndf_p218. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players\ndf_p218. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_p218. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=5, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nVertical Field\nPlay of Direction Normalized\nLine of Scrimmage Normalized\ngameId 2019092211, playId 218; left-to-right play now shown as a bottom-to-top play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T21:19:34.412573Z","iopub.execute_input":"2022-01-06T21:19:34.41286Z","iopub.status.idle":"2022-01-06T21:19:35.17569Z","shell.execute_reply.started":"2022-01-06T21:19:34.412824Z","shell.execute_reply":"2022-01-06T21:19:35.174842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Game 2018121610, Play 1339 (right-to-left play)","metadata":{}},{"cell_type":"code","source":"df_p1339 = df.query('gameId==2018121610 and playId==1339')","metadata":{"execution":{"iopub.status.busy":"2022-01-06T21:15:45.339371Z","iopub.execute_input":"2022-01-06T21:15:45.340553Z","iopub.status.idle":"2022-01-06T21:15:45.35023Z","shell.execute_reply.started":"2022-01-06T21:15:45.340494Z","shell.execute_reply":"2022-01-06T21:15:45.349377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# each record in the dataframe has an ayl_vf_NDOP_losNormalized value, which is the \n# same for all records; therefore, simply get the value from the first record\nlos = df_p1339['ayl_vf_NDOP_losNormalized'][:1]\n\n# create vertical field showing normalized line of scrimmage\nfig, ax = create_vertical_field(show_line_of_scrimmage=True, line_of_scrimmage=los)\n\n# plot positions of offensive players\ndf_p1339. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players\ndf_p1339. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football\ndf_p1339. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=5, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nVertical Field\nPlay of Direction Normalized\nLine of Scrimmage Normalized\ngameId 2018121610, playId 1339; right-to-left play now shown as a bottom-to-top play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T21:19:45.00132Z","iopub.execute_input":"2022-01-06T21:19:45.001597Z","iopub.status.idle":"2022-01-06T21:19:45.655886Z","shell.execute_reply.started":"2022-01-06T21:19:45.001568Z","shell.execute_reply":"2022-01-06T21:19:45.655027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# each record in the dataframe has an ayl_vf_NDOP_losNormalized value, which is the \n# same for all records; therefore, simply get the value from the first record\nlos = df_p1339['ayl_vf_NDOP_losNormalized'][:1]\n\n# create vertical field showing normalized line of scrimmage\nfig, ax = create_vertical_field(show_line_of_scrimmage=True, line_of_scrimmage=los)\n\n# plot positions of offensive players for both plays\ndf_p218 \\\n    .query(\"team=='home'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\ndf_p1339. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='orange', \n         marker='o', \n         s=50)\n\n# plot positions of defensive players for both plays\ndf_p218. \\\n    query(\"team=='away'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\ndf_p1339. \\\n    query(\"team=='home'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=10, \n         kind='scatter', \n         ax=ax, \n         color='crimson', \n         marker='o', \n         s=50)\n\n# plot position of the football for both plays\ndf_p218. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=5, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', s=50)\ndf_p1339. \\\n    query(\"team=='football'\"). \\\n    plot(x='x_vf_NDOP_losNormalized', \n         y='y_vf_NDOP_losNormalized', \n         zorder=5, \n         kind='scatter', \n         ax=ax, \n         color='yellow', \n         marker='D', \n         s=50)\n\ntitle = \"\"\"\nGunners and Vises\nVertical Field Showing Multiple Plays\nPlay of Direction Normalized\nLine of Scrimmage Normalized\nPlays:\n  * gameId 2019092211, playId 218; left-to-right play now shown as a bottom-to-top play\n  * gameId 2018121610, playId 1339; right-to-left play now shown as a bottom-to-top play\n\"\"\"\nplt.title(title, loc='left')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-06T21:28:11.105068Z","iopub.execute_input":"2022-01-06T21:28:11.105385Z","iopub.status.idle":"2022-01-06T21:28:11.991763Z","shell.execute_reply.started":"2022-01-06T21:28:11.105352Z","shell.execute_reply":"2022-01-06T21:28:11.990828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}