{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# CMI - exploratory data analysis\n\nExploratory data analysis for the [CMI - Detect Behavior with Sensor Data](https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data) competition.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:05.101636Z","iopub.execute_input":"2025-06-04T05:54:05.102036Z","iopub.status.idle":"2025-06-04T05:54:05.107057Z","shell.execute_reply.started":"2025-06-04T05:54:05.102001Z","shell.execute_reply":"2025-06-04T05:54:05.106120Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"SEED = 42","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:05.108513Z","iopub.execute_input":"2025-06-04T05:54:05.108770Z","iopub.status.idle":"2025-06-04T05:54:05.126640Z","shell.execute_reply.started":"2025-06-04T05:54:05.108751Z","shell.execute_reply":"2025-06-04T05:54:05.125674Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load data","metadata":{}},{"cell_type":"code","source":"import pathlib\n\nFILE_DIR = pathlib.Path('/kaggle/input/cmi-detect-behavior-with-sensor-data')  \nfiles = [f for f in FILE_DIR.iterdir() if f.is_file()]\n\nfor file in files:\n    print(file)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:05.127630Z","iopub.execute_input":"2025-06-04T05:54:05.128267Z","iopub.status.idle":"2025-06-04T05:54:05.151054Z","shell.execute_reply.started":"2025-06-04T05:54:05.128233Z","shell.execute_reply":"2025-06-04T05:54:05.150224Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\ntrain_df = pd.read_csv(FILE_DIR / 'train.csv')\ntrain_demographics_df = pd.read_csv(FILE_DIR / 'train_demographics.csv')\ntest_df = pd.read_csv(FILE_DIR / 'test.csv')\ntest_demographics_df = pd.read_csv(FILE_DIR / 'test_demographics.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:05.151993Z","iopub.execute_input":"2025-06-04T05:54:05.152354Z","iopub.status.idle":"2025-06-04T05:54:31.856493Z","shell.execute_reply.started":"2025-06-04T05:54:05.152324Z","shell.execute_reply":"2025-06-04T05:54:31.855520Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"display(train_df.head(3))\nprint(train_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:31.858729Z","iopub.execute_input":"2025-06-04T05:54:31.859071Z","iopub.status.idle":"2025-06-04T05:54:31.881353Z","shell.execute_reply.started":"2025-06-04T05:54:31.858993Z","shell.execute_reply":"2025-06-04T05:54:31.880476Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"display(train_demographics_df.head(3))\nprint(train_demographics_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:31.882292Z","iopub.execute_input":"2025-06-04T05:54:31.882533Z","iopub.status.idle":"2025-06-04T05:54:31.906004Z","shell.execute_reply.started":"2025-06-04T05:54:31.882508Z","shell.execute_reply":"2025-06-04T05:54:31.904459Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Merge `train` with `train_demographics`.","metadata":{}},{"cell_type":"markdown","source":"## Data structure","metadata":{}},{"cell_type":"code","source":"train_df = pd.merge(train_df, train_demographics_df, how=\"left\", on=\"subject\")\ntest_df = pd.merge(test_df, test_demographics_df, how=\"left\", on=\"subject\")\n\nprint(f\"train shape {train_df.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:31.908314Z","iopub.execute_input":"2025-06-04T05:54:31.909283Z","iopub.status.idle":"2025-06-04T05:54:32.615979Z","shell.execute_reply.started":"2025-06-04T05:54:31.909222Z","shell.execute_reply":"2025-06-04T05:54:32.614982Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.phase.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.617415Z","iopub.execute_input":"2025-06-04T05:54:32.617695Z","iopub.status.idle":"2025-06-04T05:54:32.653732Z","shell.execute_reply.started":"2025-06-04T05:54:32.617676Z","shell.execute_reply":"2025-06-04T05:54:32.652516Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.behavior.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.654866Z","iopub.execute_input":"2025-06-04T05:54:32.655202Z","iopub.status.idle":"2025-06-04T05:54:32.700942Z","shell.execute_reply.started":"2025-06-04T05:54:32.655160Z","shell.execute_reply":"2025-06-04T05:54:32.699837Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Which columns besides the target `gesture`are not availabe in the test set?","metadata":{}},{"cell_type":"code","source":"print(set(train_df.columns) - set(test_df.columns) - set(['gesture']))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.701790Z","iopub.execute_input":"2025-06-04T05:54:32.702221Z","iopub.status.idle":"2025-06-04T05:54:32.708274Z","shell.execute_reply.started":"2025-06-04T05:54:32.702170Z","shell.execute_reply":"2025-06-04T05:54:32.707050Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.dtypes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.709632Z","iopub.execute_input":"2025-06-04T05:54:32.709881Z","iopub.status.idle":"2025-06-04T05:54:32.730608Z","shell.execute_reply.started":"2025-06-04T05:54:32.709862Z","shell.execute_reply":"2025-06-04T05:54:32.729565Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"imu_cols = [col for col in train_df.columns if col.startswith(\"tof\") or col.startswith(\"acc\") or col.startswith(\"rot\") or col.startswith(\"thm\")]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.731757Z","iopub.execute_input":"2025-06-04T05:54:32.732119Z","iopub.status.idle":"2025-06-04T05:54:32.749735Z","shell.execute_reply.started":"2025-06-04T05:54:32.732046Z","shell.execute_reply":"2025-06-04T05:54:32.748637Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"In this competion one goal is to differentiate between Body-focused repetitive behaviors (BFRB) and non-BFRB-like gestures.","metadata":{}},{"cell_type":"code","source":"BFRB_gestures = [\"Above ear - pull hair\", \"Forehead - pull hairline\", \"Forehead - scratch\", \"Eyebrow - pull hair\", \n                 \"Eyelash - pull hair\", \"Neck - pinch skin\", \"Neck - scratch\", \"Cheek - pinch skin\"]\n\ntrain_df[\"BFRB\"] = train_df.gesture.isin(BFRB_gestures)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.753619Z","iopub.execute_input":"2025-06-04T05:54:32.753919Z","iopub.status.idle":"2025-06-04T05:54:32.794342Z","shell.execute_reply.started":"2025-06-04T05:54:32.753897Z","shell.execute_reply":"2025-06-04T05:54:32.793210Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sensor_df = train_df.set_index(\"row_id\")[imu_cols]\nnon_sensor_df = train_df.drop(columns=imu_cols)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:32.795377Z","iopub.execute_input":"2025-06-04T05:54:32.795703Z","iopub.status.idle":"2025-06-04T05:54:35.495398Z","shell.execute_reply.started":"2025-06-04T05:54:32.795673Z","shell.execute_reply":"2025-06-04T05:54:35.494364Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Check for missing values","metadata":{}},{"cell_type":"code","source":"display(train_df.isna().sum().sort_values(ascending=False))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:35.496604Z","iopub.execute_input":"2025-06-04T05:54:35.496975Z","iopub.status.idle":"2025-06-04T05:54:36.431241Z","shell.execute_reply.started":"2025-06-04T05:54:35.496943Z","shell.execute_reply":"2025-06-04T05:54:36.430281Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"From the [data sescription](https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/data) we know that IMU sensor data is not provided for all sequences. In fact, the test set will only include IMU sensor data for half of the data.","metadata":{}},{"cell_type":"code","source":"missing_percentage = train_df.isna().groupby(train_df['sequence_id']).mean() * 100 \nmissing_percentage.max().sort_values(ascending=False).unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:36.432052Z","iopub.execute_input":"2025-06-04T05:54:36.432321Z","iopub.status.idle":"2025-06-04T05:54:38.793368Z","shell.execute_reply.started":"2025-06-04T05:54:36.432300Z","shell.execute_reply":"2025-06-04T05:54:38.792270Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"All values are either present or missing from the whole sequence. There are no missing values within sequences.","metadata":{}},{"cell_type":"markdown","source":"# Non-sensor data\n\n## Target","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\n# sns.set(style=\"whitegrid\")\nsns.set_style(\"darkgrid\")\nsns.set_palette(\"dark\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:38.794366Z","iopub.execute_input":"2025-06-04T05:54:38.794673Z","iopub.status.idle":"2025-06-04T05:54:38.801254Z","shell.execute_reply.started":"2025-06-04T05:54:38.794643Z","shell.execute_reply":"2025-06-04T05:54:38.799505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"seq = non_sensor_df.groupby(\"sequence_id\").agg({'gesture' : 'nunique'})\nprint(len(seq), seq.gesture.max())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:38.803080Z","iopub.execute_input":"2025-06-04T05:54:38.803463Z","iopub.status.idle":"2025-06-04T05:54:38.907551Z","shell.execute_reply.started":"2025-06-04T05:54:38.803436Z","shell.execute_reply":"2025-06-04T05:54:38.906520Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"There are 8151 sequences, each one with a unique `gesture` for each seaquence.","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(10, 8))\n\nnon_sensor_df.groupby(\"gesture\").count()[\"sequence_id\"].sort_values(ascending=False).plot.bar(ax=axes[0], color='#1f77b4')\naxes[0].set_title(\"Gesture by sequence count\")\naxes[0].set_ylabel(\"Count\")\n\nnon_sensor_df.groupby(\"BFRB\").count()[\"sequence_id\"].plot.bar(ax=axes[1], color='#1f77b4')\naxes[1].set_title(\"BFRB by sequence count\")\naxes[1].set_ylabel(\"Count\")\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:38.908501Z","iopub.execute_input":"2025-06-04T05:54:38.908731Z","iopub.status.idle":"2025-06-04T05:54:40.033332Z","shell.execute_reply.started":"2025-06-04T05:54:38.908714Z","shell.execute_reply":"2025-06-04T05:54:40.032284Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Sequence length","metadata":{}},{"cell_type":"code","source":"seq_len = non_sensor_df.groupby('sequence_id').size().reset_index(name='seq_len').sort_values(by=\"seq_len\", ascending=False)\n\nsns.violinplot(seq_len);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:40.034333Z","iopub.execute_input":"2025-06-04T05:54:40.034620Z","iopub.status.idle":"2025-06-04T05:54:40.300715Z","shell.execute_reply.started":"2025-06-04T05:54:40.034585Z","shell.execute_reply":"2025-06-04T05:54:40.299553Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The sequences vary in length drastically","metadata":{}},{"cell_type":"markdown","source":"## Distributions for non-sensor data by row\n\nKeep in mind that the length of sequences varies a lot.","metadata":{}},{"cell_type":"code","source":"num_cols = ['age', 'height_cm', 'shoulder_to_wrist_cm', 'elbow_to_wrist_cm']\ncat_cols = list(set(non_sensor_df.columns) - set(num_cols) - set(['gesture', 'subject', 'sequence_counter', 'sequence_id', 'row_id', 'BFRB']))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:40.301856Z","iopub.execute_input":"2025-06-04T05:54:40.302222Z","iopub.status.idle":"2025-06-04T05:54:40.307844Z","shell.execute_reply.started":"2025-06-04T05:54:40.302158Z","shell.execute_reply":"2025-06-04T05:54:40.306556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm.notebook import tqdm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:40.308919Z","iopub.execute_input":"2025-06-04T05:54:40.309258Z","iopub.status.idle":"2025-06-04T05:54:40.339370Z","shell.execute_reply.started":"2025-06-04T05:54:40.309232Z","shell.execute_reply":"2025-06-04T05:54:40.337509Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Look into categorical columns by `gesture`","metadata":{}},{"cell_type":"code","source":"for col in tqdm(cat_cols):\n    plt.figure(figsize=(16, 4))\n    sns.countplot(data=non_sensor_df, x=\"gesture\", hue=col, palette=\"Set2\")\n    plt.xticks(rotation=90);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:40.340518Z","iopub.execute_input":"2025-06-04T05:54:40.340852Z","iopub.status.idle":"2025-06-04T05:54:48.415912Z","shell.execute_reply.started":"2025-06-04T05:54:40.340818Z","shell.execute_reply":"2025-06-04T05:54:48.414737Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Look into categorical columns by `BFRB`","metadata":{}},{"cell_type":"code","source":"for col in tqdm(cat_cols):\n    plt.figure(figsize=(16, 4))\n    sns.countplot(data=non_sensor_df, x=\"BFRB\", hue=col, palette=\"Set2\")\n    plt.xticks(rotation=90);\n    plt.title(col);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:48.417210Z","iopub.execute_input":"2025-06-04T05:54:48.417572Z","iopub.status.idle":"2025-06-04T05:54:51.707476Z","shell.execute_reply.started":"2025-06-04T05:54:48.417542Z","shell.execute_reply":"2025-06-04T05:54:51.706558Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Look into numerical columns by `gesture`","metadata":{}},{"cell_type":"code","source":"for col in tqdm(num_cols):\n    plt.figure(figsize=(16, 4))\n    sns.boxplot(x='gesture', y=col, data=non_sensor_df, palette='viridis')\n    plt.title(col);\n    plt.xticks(rotation=90);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:51.708740Z","iopub.execute_input":"2025-06-04T05:54:51.709393Z","iopub.status.idle":"2025-06-04T05:54:55.230171Z","shell.execute_reply.started":"2025-06-04T05:54:51.709363Z","shell.execute_reply":"2025-06-04T05:54:55.229265Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Look into numerical columns by `BFRB`","metadata":{}},{"cell_type":"code","source":"for col in tqdm(num_cols):\n    plt.figure(figsize=(16, 4))\n    sns.boxplot(x='BFRB', y=col, data=non_sensor_df, palette='viridis')\n    plt.title(col);\n    plt.xticks(rotation=90);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:55.231292Z","iopub.execute_input":"2025-06-04T05:54:55.231595Z","iopub.status.idle":"2025-06-04T05:54:56.837569Z","shell.execute_reply.started":"2025-06-04T05:54:55.231565Z","shell.execute_reply":"2025-06-04T05:54:56.836616Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# IMU sensors","metadata":{}},{"cell_type":"markdown","source":"Create images from the IMU sensor fields","metadata":{}},{"cell_type":"code","source":"sensor_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:56.838621Z","iopub.execute_input":"2025-06-04T05:54:56.838968Z","iopub.status.idle":"2025-06-04T05:54:56.864626Z","shell.execute_reply.started":"2025-06-04T05:54:56.838937Z","shell.execute_reply":"2025-06-04T05:54:56.863625Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Visualise time-of-flight `tof`","metadata":{}},{"cell_type":"code","source":"def plot_sensor_images(row):\n    \n    plt.figure(figsize=(15, 3))\n    \n    for sensor in range(1,6):\n        mat = []\n        for i in range(64):\n            mat.append(sensor_df.iloc[row][f\"tof_{sensor}_v{i}\"])\n        \n        plt.subplot(1, 5, sensor)\n        mat = np.array(mat).reshape(8,8)\n        plt.imshow(mat)\n        plt.title(f\"{sensor_df.iloc[row].name} - tof_{sensor}\")\n\n# plot_sensor_images(row=0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:56.865992Z","iopub.execute_input":"2025-06-04T05:54:56.866566Z","iopub.status.idle":"2025-06-04T05:54:56.883396Z","shell.execute_reply.started":"2025-06-04T05:54:56.866531Z","shell.execute_reply":"2025-06-04T05:54:56.882258Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Check the `tof` sensor images for random sample for each `gesture`.","metadata":{}},{"cell_type":"code","source":"for gest in non_sensor_df.gesture.unique():\n    sample_row = non_sensor_df[non_sensor_df['gesture'] == gest].sample(n=1, random_state=SEED).index[0]\n    plot_sensor_images(row=sample_row)\n    plt.suptitle(gest);\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:54:56.884382Z","iopub.execute_input":"2025-06-04T05:54:56.884655Z","iopub.status.idle":"2025-06-04T05:55:18.655281Z","shell.execute_reply.started":"2025-06-04T05:54:56.884636Z","shell.execute_reply":"2025-06-04T05:55:18.654117Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Thermopile  sensors","metadata":{}},{"cell_type":"code","source":"thm_cols = sensor_df.filter(like='thm', axis=1).columns.values\nsensor_df[thm_cols].min(), sensor_df[thm_cols].max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:55:18.656411Z","iopub.execute_input":"2025-06-04T05:55:18.656748Z","iopub.status.idle":"2025-06-04T05:55:18.693066Z","shell.execute_reply.started":"2025-06-04T05:55:18.656715Z","shell.execute_reply":"2025-06-04T05:55:18.692071Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"According to the specifications the values are in degree Celsius. Values ariund zero are likely measurement issues.","metadata":{}},{"cell_type":"code","source":"thm_data = pd.DataFrame(non_sensor_df.set_index(\"row_id\")[[\"gesture\", \"BFRB\"]]).join(sensor_df[thm_cols])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:55:18.694279Z","iopub.execute_input":"2025-06-04T05:55:18.694578Z","iopub.status.idle":"2025-06-04T05:55:18.895818Z","shell.execute_reply.started":"2025-06-04T05:55:18.694556Z","shell.execute_reply":"2025-06-04T05:55:18.894727Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Let's have a look at the thermopile data by `gesture`","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(5, 1, figsize=(10, len(thm_cols)*6), sharey=False)\n\nfor i, col in enumerate(thm_cols):\n    \n    sns.boxplot(x='gesture', y=col, data=thm_data, ax=axes[i], palette='viridis')\n\n    axes[i].set_title(f'Boxplot of {col} by Gesture')\n    axes[i].set_xlabel('gesture') \n    axes[i].set_ylabel(f'{col} Value')\n    axes[i].tick_params(axis='x', rotation=90) \n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:55:18.898091Z","iopub.execute_input":"2025-06-04T05:55:18.898435Z","iopub.status.idle":"2025-06-04T05:55:24.301259Z","shell.execute_reply.started":"2025-06-04T05:55:18.898409Z","shell.execute_reply":"2025-06-04T05:55:24.300218Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"and by `BFRB`","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(5, 1, figsize=(10, len(thm_cols)*5), sharey=False)\n\nfor i, col in enumerate(thm_cols):\n    \n    sns.boxplot(x='BFRB', y=col, data=thm_data, ax=axes[i], palette='viridis')\n\n    axes[i].set_title(f'Boxplot of {col} by Gesture')\n    axes[i].set_xlabel('gesture') \n    axes[i].set_ylabel(f'{col} Value')\n    axes[i].tick_params(axis='x', rotation=90) \n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-04T05:55:24.302473Z","iopub.execute_input":"2025-06-04T05:55:24.302782Z","iopub.status.idle":"2025-06-04T05:55:26.999435Z","shell.execute_reply.started":"2025-06-04T05:55:24.302750Z","shell.execute_reply":"2025-06-04T05:55:26.998309Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}