{"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":"2023-01-03T12:54:11.760536Z","iopub.execute_input":"2023-01-03T12:54:11.760891Z","iopub.status.idle":"2023-01-03T12:54:11.908958Z","shell.execute_reply.started":"2023-01-03T12:54:11.760859Z","shell.execute_reply":"2023-01-03T12:54:11.907969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"前几年，NFL在Kaggle社区创建头盔碰撞检测与识别算法。\n在本场比赛中，任务：检测球员彼此接触时刻、球员身体与地面接触的时刻。\n","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport glob\nimport numpy as np\nimport os\nimport cv2\nimport subprocess\nimport plotly.express as px\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom base64 import b64encode\nfrom IPython.display import HTML, Video, display\nfrom colorama import Fore, Back, Style","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:54:14.704974Z","iopub.execute_input":"2023-01-03T12:54:14.705539Z","iopub.status.idle":"2023-01-03T12:54:14.711423Z","shell.execute_reply.started":"2023-01-03T12:54:14.705504Z","shell.execute_reply":"2023-01-03T12:54:14.710011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_video_metadata.csv')\ntest_metadata_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/test_video_metadata.csv')","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:55:08.30328Z","iopub.execute_input":"2023-01-03T12:55:08.303632Z","iopub.status.idle":"2023-01-03T12:55:08.331063Z","shell.execute_reply.started":"2023-01-03T12:55:08.303591Z","shell.execute_reply":"2023-01-03T12:55:08.329765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata_df['end_time'] = train_metadata_df.end_time.apply(pd.to_datetime)\ntrain_metadata_df['start_time'] = train_metadata_df.start_time.apply(pd.to_datetime)\n\ntrain_metadata_df['duration'] = (train_metadata_df['end_time'] - train_metadata_df['start_time']).dt.total_seconds()\n\nprint(f\"Shape => {train_metadata_df.shape}\")\ntrain_metadata_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:55:26.133905Z","iopub.execute_input":"2023-01-03T12:55:26.134437Z","iopub.status.idle":"2023-01-03T12:55:26.237801Z","shell.execute_reply.started":"2023-01-03T12:55:26.134387Z","shell.execute_reply":"2023-01-03T12:55:26.237063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata_df.game_play.nunique()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:55:38.134519Z","iopub.execute_input":"2023-01-03T12:55:38.134865Z","iopub.status.idle":"2023-01-03T12:55:38.144809Z","shell.execute_reply.started":"2023-01-03T12:55:38.134836Z","shell.execute_reply":"2023-01-03T12:55:38.143589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata_df.view.value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:55:46.578821Z","iopub.execute_input":"2023-01-03T12:55:46.5803Z","iopub.status.idle":"2023-01-03T12:55:46.591186Z","shell.execute_reply.started":"2023-01-03T12:55:46.580243Z","shell.execute_reply":"2023-01-03T12:55:46.589748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.box(x=train_metadata_df['duration'],\n             template='simple_white',\n             title='Distribution of duration',\n             labels={'x': 'Time (in sec.)'},\n             \n             color_discrete_sequence=px.colors.sequential.Burg_r)\n\nfig.update_layout(coloraxis_showscale=False)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:55:54.959444Z","iopub.execute_input":"2023-01-03T12:55:54.959808Z","iopub.status.idle":"2023-01-03T12:55:56.347355Z","shell.execute_reply.started":"2023-01-03T12:55:54.959776Z","shell.execute_reply":"2023-01-03T12:55:56.346017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_metadata_df['end_time'] = test_metadata_df.end_time.apply(pd.to_datetime)\ntest_metadata_df['start_time'] = test_metadata_df.start_time.apply(pd.to_datetime)\n\ntest_metadata_df['duration'] = (test_metadata_df['end_time'] - test_metadata_df['start_time']).dt.total_seconds()\n\nprint(f\"Shape => {test_metadata_df.shape}\")\ntest_metadata_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:56:05.237286Z","iopub.execute_input":"2023-01-03T12:56:05.237645Z","iopub.status.idle":"2023-01-03T12:56:05.260724Z","shell.execute_reply.started":"2023-01-03T12:56:05.237615Z","shell.execute_reply":"2023-01-03T12:56:05.259694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_labels.csv')","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:56:26.256416Z","iopub.execute_input":"2023-01-03T12:56:26.256842Z","iopub.status.idle":"2023-01-03T12:56:36.188073Z","shell.execute_reply.started":"2023-01-03T12:56:26.256805Z","shell.execute_reply":"2023-01-03T12:56:36.186691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Shape => {train_labels_df.shape}\")\ntrain_labels_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:56:52.90125Z","iopub.execute_input":"2023-01-03T12:56:52.901636Z","iopub.status.idle":"2023-01-03T12:56:52.915504Z","shell.execute_reply.started":"2023-01-03T12:56:52.901596Z","shell.execute_reply":"2023-01-03T12:56:52.914048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_fps_dict = {\n    'video': [],\n    'fps': [],\n    'width': [],\n    'height': [],\n}\n\nfor vid_file in glob.glob('./nfl-player-contact-detection_data/train/*'):\n    vidcap = cv2.VideoCapture(vid_file)\n    vid_name = vid_file.split(os.sep)[-1]\n\n    fps = round(vidcap.get(cv2.CAP_PROP_FPS))\n    width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))\n    height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n    train_fps_dict['video'].append(vid_name)\n    train_fps_dict['fps'].append(fps)\n    train_fps_dict['width'].append(width)\n    train_fps_dict['height'].append(height)","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:56:57.591728Z","iopub.execute_input":"2023-01-03T12:56:57.592151Z","iopub.status.idle":"2023-01-03T12:56:57.600765Z","shell.execute_reply.started":"2023-01-03T12:56:57.592119Z","shell.execute_reply":"2023-01-03T12:56:57.599106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_fps_df = pd.DataFrame(train_fps_dict)\nprint(train_fps_df.fps.value_counts()); print()\nprint(train_fps_df.width.value_counts()); print()\nprint(train_fps_df.height.value_counts())","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:57:06.445144Z","iopub.execute_input":"2023-01-03T12:57:06.445647Z","iopub.status.idle":"2023-01-03T12:57:06.458024Z","shell.execute_reply.started":"2023-01-03T12:57:06.445612Z","shell.execute_reply":"2023-01-03T12:57:06.457142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_fps_dict = {\n    'video': [],\n    'fps': [],\n    'width': [],\n    'height': [],\n}\n\nfor vid_file in glob.glob('./nfl-player-contact-detection_data/test/*'):\n    vidcap = cv2.VideoCapture(vid_file)\n    vid_name = vid_file.split(os.sep)[-1]\n\n    fps = round(vidcap.get(cv2.CAP_PROP_FPS))\n    width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))\n    height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n    test_fps_dict['video'].append(vid_name)\n    test_fps_dict['fps'].append(fps)\n    test_fps_dict['width'].append(width)\n    test_fps_dict['height'].append(height)","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:57:15.643245Z","iopub.execute_input":"2023-01-03T12:57:15.643623Z","iopub.status.idle":"2023-01-03T12:57:15.652094Z","shell.execute_reply.started":"2023-01-03T12:57:15.643591Z","shell.execute_reply":"2023-01-03T12:57:15.650733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_fps_df = pd.DataFrame(test_fps_dict)\nprint(test_fps_df.fps.value_counts()); print()\nprint(test_fps_df.width.value_counts()); print()\nprint(test_fps_df.height.value_counts())","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:57:23.417277Z","iopub.execute_input":"2023-01-03T12:57:23.417661Z","iopub.status.idle":"2023-01-03T12:57:23.426523Z","shell.execute_reply.started":"2023-01-03T12:57:23.417629Z","shell.execute_reply":"2023-01-03T12:57:23.425667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_baseline_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_baseline_helmets.csv')\ntest_baseline_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/test_baseline_helmets.csv')","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:58:06.643523Z","iopub.execute_input":"2023-01-03T12:58:06.643888Z","iopub.status.idle":"2023-01-03T12:58:13.587559Z","shell.execute_reply.started":"2023-01-03T12:58:06.643856Z","shell.execute_reply":"2023-01-03T12:58:13.586819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Shape => {train_baseline_df.shape}\")\ntrain_baseline_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:58:14.637799Z","iopub.execute_input":"2023-01-03T12:58:14.639046Z","iopub.status.idle":"2023-01-03T12:58:14.655671Z","shell.execute_reply.started":"2023-01-03T12:58:14.638997Z","shell.execute_reply":"2023-01-03T12:58:14.653965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_frames = train_baseline_df[train_baseline_df.game_play=='58168_003392'].frame.nunique()\nnum_steps = train_labels_df[train_labels_df.game_play=='58168_003392'].step.nunique()\n\nprint('Num frames (from time the game start):', num_frames)\nprint('Num steps (from time the game start):', num_steps)","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:58:23.957329Z","iopub.execute_input":"2023-01-03T12:58:23.958504Z","iopub.status.idle":"2023-01-03T12:58:24.468746Z","shell.execute_reply.started":"2023-01-03T12:58:23.958465Z","shell.execute_reply":"2023-01-03T12:58:24.466949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 检查是否有缺失值\ntrain_baseline_df.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:58:34.079123Z","iopub.execute_input":"2023-01-03T12:58:34.07958Z","iopub.status.idle":"2023-01-03T12:58:34.619143Z","shell.execute_reply.started":"2023-01-03T12:58:34.079544Z","shell.execute_reply":"2023-01-03T12:58:34.618002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 直方图和箱线图的左边，宽度，顶部，高度\ncols = ['top', 'left', 'width', 'height']\n\nfor idx, col in enumerate(cols):\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n    sns.histplot(train_baseline_df, x=train_baseline_df[col], kde=True, hue=None,\n                 color=sns.color_palette('hls', train_baseline_df.shape[1])[idx], ax=ax1)\n    \n    sns.boxplot(x=train_baseline_df[col], width=.4, linewidth=4, fliersize=2.5,\n                color=sns.color_palette('hls', train_baseline_df.shape[1])[idx], ax=ax2)\n    \n    fig.suptitle(f'Histogram and Boxplot of {col}', size=20, y=1.02)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:58:44.126457Z","iopub.execute_input":"2023-01-03T12:58:44.126808Z","iopub.status.idle":"2023-01-03T12:59:47.110012Z","shell.execute_reply.started":"2023-01-03T12:58:44.126778Z","shell.execute_reply":"2023-01-03T12:59:47.10888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_baseline_df[train_baseline_df.view == 'Endzone2']","metadata":{"execution":{"iopub.status.busy":"2023-01-03T12:59:47.11181Z","iopub.execute_input":"2023-01-03T12:59:47.1122Z","iopub.status.idle":"2023-01-03T12:59:47.351017Z","shell.execute_reply.started":"2023-01-03T12:59:47.112138Z","shell.execute_reply":"2023-01-03T12:59:47.349456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def video_with_helmets(video_path, baseline_boxes, labels_df=None, verbose=True):\n    \"\"\"\n    Annotates a video with baseline model boxes and labels\n    \"\"\"\n    VIDEO_CODEC = \"MP4V\"\n    HELMET_TEXT_COLOR = (0, 0, 0)  # Black\n    HELMET_FREE_COLOR = (0, 0, 0)  # when player does not has any contact\n    HELMET_CONTACT_COLOR = (0, 255, 0)  # when player has contact with other player\n    HELMET_GROUND_COLOR = (0, 0, 255)  # when player has contact with ground\n    video_name = os.path.basename(video_path)\n    video_basename = video_name.rsplit('_', 1)[0]\n    if verbose:\n        print(f\"Running for {video_name}\")\n    baseline_boxes = baseline_boxes.copy()\n\n    vidcap = cv2.VideoCapture(video_path)\n    fps = vidcap.get(cv2.CAP_PROP_FPS)\n    width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))\n    height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n    output_path = \"labeled_\" + video_name\n    tmp_output_path = \"tmp_\" + output_path\n    output_video = cv2.VideoWriter(\n        tmp_output_path, cv2.VideoWriter_fourcc(*VIDEO_CODEC), fps, (width, height)\n    )\n\n    frame = 0\n    count_frame_for_each_step = 0  # Reset after 6 frame\n    step = 0\n    while True:\n        it_worked, img = vidcap.read()\n        if not it_worked:\n            break\n\n        frame += 1\n        img_name = video_name.replace(\".mp4\", \"\")\n        cv2.putText(img, img_name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, HELMET_TEXT_COLOR, thickness=1)\n\n        cv2.putText(img, str(frame), (width - 90, height - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, HELMET_TEXT_COLOR, thickness=1)\n\n        # Add box\n        boxes = baseline_boxes.query(\"video == @video_name and frame == @frame\")\n        \n        if len(boxes): # When the game has started\n            # print(step)\n            if labels_df is not None:\n                labels = labels_df.query(\"game_play == @video_basename and step == @step\")\n                for box in boxes.itertuples(index=False):  # When the game has started\n                    labels_player = labels[(labels.nfl_player_id_1 == box.nfl_player_id) | (labels.nfl_player_id_2 == box.nfl_player_id)]\n                    labels_player = labels_player[labels_player.contact != 0]  # select contact time\n                    if len(labels_player) == 0:  # if no contact with current player\n                        cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                    HELMET_FREE_COLOR, thickness=2)\n                    else:  # if any contact\n                        if labels_player.iloc[-1].nfl_player_id_2 == 'G':  # if contact with ground\n                            cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                        HELMET_GROUND_COLOR, thickness=2)\n                            if len(labels_player) > 1:  # if player has more than 1 contact\n                                cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                            HELMET_CONTACT_COLOR, thickness=1)\n                        else:  # if contact with other player\n                            cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                        HELMET_CONTACT_COLOR, thickness=2)\n                    cv2.putText(img, box.player_label, (box.left + 1, max(0, box.top - 20)), cv2.FONT_HERSHEY_SIMPLEX,\n                                0.5, HELMET_TEXT_COLOR, thickness=2,)\n                    \n                count_frame_for_each_step += 1\n                if count_frame_for_each_step == 6:\n                    step += 1\n                    count_frame_for_each_step = 0  # reset\n            else:\n                for box in boxes.itertuples(index=False):  # When the game has started\n                    cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                HELMET_FREE_COLOR, thickness=2)\n                    cv2.putText(img, box.player_label, (box.left + 1, max(0, box.top - 20)), cv2.FONT_HERSHEY_SIMPLEX,\n                                0.5, HELMET_TEXT_COLOR, thickness=2,)\n            \n        output_video.write(img)\n    output_video.release()\n    # Not all browsers support the codec, we will re-load the file at tmp_output_path\n    # and convert to a codec that is more broadly readable using ffmpeg\n    if os.path.exists(output_path):\n        os.remove(output_path)\n    subprocess.run(\n        [\n            \"ffmpeg\",\n            \"-i\",\n            tmp_output_path,\n            \"-crf\",\n            \"18\",\n            \"-preset\",\n            \"veryfast\",\n            \"-hide_banner\",\n            \"-loglevel\",\n            \"error\",\n            \"-vcodec\",\n            \"libx264\",\n            output_path,\n        ]\n    )\n    os.remove(tmp_output_path)\n\n    return output_path","metadata":{"execution":{"iopub.status.busy":"2023-01-03T13:00:38.358601Z","iopub.execute_input":"2023-01-03T13:00:38.358946Z","iopub.status.idle":"2023-01-03T13:00:38.382802Z","shell.execute_reply.started":"2023-01-03T13:00:38.358917Z","shell.execute_reply":"2023-01-03T13:00:38.381311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_video = \"/kaggle/input/nfl-player-contact-detection/train/58176_002844_Sideline.mp4\"\noutput_video = video_with_helmets(example_video, train_baseline_df, train_labels_df)\n\nfrac = 0.65  # scaling factor for display\ndisplay(\n    Video(data=output_video, embed=True, height=int(720 * frac), width=int(1280 * frac))\n)","metadata":{"execution":{"iopub.status.busy":"2023-01-03T13:01:02.534171Z","iopub.execute_input":"2023-01-03T13:01:02.534551Z","iopub.status.idle":"2023-01-03T13:02:43.670089Z","shell.execute_reply.started":"2023-01-03T13:01:02.534519Z","shell.execute_reply":"2023-01-03T13:02:43.668905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_video = \"/kaggle/input/nfl-player-contact-detection/train/58168_003392_Sideline.mp4\"\noutput_video = video_with_helmets(example_video, train_baseline_df, train_labels_df)\n\nfrac = 0.65  # scaling factor for display\ndisplay(\n    Video(data=output_video, embed=True, height=int(720 * frac), width=int(1280 * frac))\n)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_player_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_player_tracking.csv')\ntest_player_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/test_player_tracking.csv')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Shape => {train_player_df.shape}\")\ntrain_player_df.head(3)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Histogram and Boxplot\ncols = ['x_position', 'y_position', 'speed', 'distance', 'direction', 'orientation', 'acceleration', 'sa']\n\nfor idx, col in enumerate(cols):\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n    sns.histplot(train_player_df, x=train_player_df[col], kde=True, hue=None,\n                 color=sns.color_palette('hls', train_player_df.shape[1])[idx], ax=ax1)\n    \n    sns.boxplot(x=train_player_df[col], width=.4, linewidth=4, fliersize=2.5,\n                color=sns.color_palette('hls', train_player_df.shape[1])[idx], ax=ax2)\n    \n    fig.suptitle(f'Histogram and Boxplot of {col}', size=20, y=1.02)\n    plt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Shape => {test_player_df.shape}\")\ntest_player_df.head(3)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Histogram and Boxplot\ncols = ['x_position', 'y_position', 'speed', 'distance', 'direction', 'orientation', 'acceleration', 'sa']\n\nfor idx, col in enumerate(cols):\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n    sns.histplot(test_player_df, x=test_player_df[col], kde=True, hue=None,\n                 color=sns.color_palette('hls', test_player_df.shape[1])[idx], ax=ax1)\n    \n    sns.boxplot(x=test_player_df[col], width=.4, linewidth=4, fliersize=2.5,\n                color=sns.color_palette('hls', test_player_df.shape[1])[idx], ax=ax2)\n    \n    fig.suptitle(f'Histogram and Boxplot of {col}', size=20, y=1.02)\n    plt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sb = pd.read_csv('./nfl-player-contact-detection_data/sample_submission.csv')\nsb.head()","metadata":{},"execution_count":null,"outputs":[]}]}