{"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":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Configure visualizations\nsns.set(style=\"whitegrid\")\nplt.rcParams[\"figure.figsize\"] = (14, 6)\nimport os\n\nimport pandas as pd\n\n\nimport kaggle_evaluation.cmi_inference_server","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-31T09:58:12.845674Z","iopub.execute_input":"2025-05-31T09:58:12.845922Z","iopub.status.idle":"2025-05-31T09:58:17.238343Z","shell.execute_reply.started":"2025-05-31T09:58:12.845880Z","shell.execute_reply":"2025-05-31T09:58:17.237341Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv\")  # Replace with your actual path\ntrain_demo = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train_demographics.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:02:51.731730Z","iopub.execute_input":"2025-05-31T10:02:51.732550Z","iopub.status.idle":"2025-05-31T10:03:28.172427Z","shell.execute_reply.started":"2025-05-31T10:02:51.732522Z","shell.execute_reply":"2025-05-31T10:03:28.171406Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train Shape:\", train.shape)\nprint(\"Train Demographics Shape:\", train_demo.shape)\n\n# Display column types and null values\nprint(train.info())\nprint(train_demo.info())\n\n# Unique labels\nprint(\"Unique gestures:\", train['gesture'].unique())\nprint(\"Unique behaviors:\", train['behavior'].unique())\nprint(\"Unique orientations:\", train['orientation'].unique())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:03:28.173684Z","iopub.execute_input":"2025-05-31T10:03:28.174077Z","iopub.status.idle":"2025-05-31T10:03:28.322671Z","shell.execute_reply.started":"2025-05-31T10:03:28.174046Z","shell.execute_reply":"2025-05-31T10:03:28.321730Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train_demo.describe(include='all'))\n\n# Distribution of subjects, age, sex\nsns.countplot(data=train_demo, x='sex')\nplt.title(\"Sex Distribution\")\nplt.show()\n\nsns.histplot(train_demo['age'], bins=20, kde=True)\nplt.title(\"Age Distribution\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:11:29.477411Z","iopub.execute_input":"2025-05-31T10:11:29.477764Z","iopub.status.idle":"2025-05-31T10:11:30.212092Z","shell.execute_reply.started":"2025-05-31T10:11:29.477717Z","shell.execute_reply":"2025-05-31T10:11:30.211145Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Gesture distribution\nsns.countplot(data=train, y='gesture', order=train['gesture'].value_counts().index)\nplt.title(\"Gesture Frequency\")\nplt.show()\n\n# Target vs Non-target\nsns.countplot(data=train, x='sequence_type')\nplt.title(\"Target vs Non-Target Gestures\")\nplt.show()\n\n# Orientation distribution\nsns.countplot(data=train, y='orientation', order=train['orientation'].value_counts().index)\nplt.title(\"Body Orientation\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:11:41.464834Z","iopub.execute_input":"2025-05-31T10:11:41.465504Z","iopub.status.idle":"2025-05-31T10:11:43.012981Z","shell.execute_reply.started":"2025-05-31T10:11:41.465465Z","shell.execute_reply":"2025-05-31T10:11:43.012091Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"example_seq_id = train['sequence_id'].unique()[0]\nexample_seq = train[train['sequence_id'] == example_seq_id]\n\nplt.plot(example_seq['sequence_counter'], example_seq['acc_x'], label='acc_x')\nplt.plot(example_seq['sequence_counter'], example_seq['acc_y'], label='acc_y')\nplt.plot(example_seq['sequence_counter'], example_seq['acc_z'], label='acc_z')\nplt.title(f\"Accelerometer Data for Sequence {example_seq_id}\")\nplt.xlabel(\"Sequence Step\")\nplt.ylabel(\"Acceleration (m/s^2)\")\nplt.legend()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:11:47.900365Z","iopub.execute_input":"2025-05-31T10:11:47.900643Z","iopub.status.idle":"2025-05-31T10:11:48.264833Z","shell.execute_reply.started":"2025-05-31T10:11:47.900622Z","shell.execute_reply":"2025-05-31T10:11:48.263849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tof_cols = [col for col in train.columns if col.startswith('tof_')]\n\nmissing_tof = (train[tof_cols] == -1).mean().sort_values(ascending=False) * 100\nmissing_tof.head(30).plot(kind='bar', title=\"Top ToF Pixels with Missing Signals (-1)\")\nplt.ylabel(\"% Missing\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:11:50.035082Z","iopub.execute_input":"2025-05-31T10:11:50.035398Z","iopub.status.idle":"2025-05-31T10:11:51.490438Z","shell.execute_reply.started":"2025-05-31T10:11:50.035375Z","shell.execute_reply":"2025-05-31T10:11:51.489528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.manifold import TSNE\nfrom sklearn.decomposition import PCA\nimport umap\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# Aggregate features per sequence\nagg_features = train.groupby(\"sequence_id\").agg({\n    'acc_x': 'mean', 'acc_y': 'mean', 'acc_z': 'mean',\n    'rot_x': 'mean', 'rot_y': 'mean', 'rot_z': 'mean',\n    'thm_1': 'mean', 'thm_2': 'mean', 'thm_3': 'mean', 'thm_4': 'mean', 'thm_5': 'mean'\n}).reset_index()\n\n# Add gesture labels\ngesture_labels = train.groupby(\"sequence_id\")[\"gesture\"].first().reset_index()\nagg_features = agg_features.merge(gesture_labels, on=\"sequence_id\")\n\n# Drop rows with any NaN values\nagg_features_clean = agg_features.dropna()\n\n# Dimensionality reduction with UMAP\nreducer = umap.UMAP(n_neighbors=15, min_dist=0.1, random_state=42)\nembedding_umap = reducer.fit_transform(\n    agg_features_clean.drop([\"sequence_id\", \"gesture\"], axis=1)\n)\n\n# Plotting\nplt.figure(figsize=(10, 6))\nsns.scatterplot(\n    x=embedding_umap[:, 0],\n    y=embedding_umap[:, 1],\n    hue=agg_features_clean[\"gesture\"],\n    palette=\"tab20\",\n    s=50\n)\nplt.title(\"UMAP projection of aggregated sensor features by gesture\")\nplt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:11:52.211636Z","iopub.execute_input":"2025-05-31T10:11:52.212017Z","iopub.status.idle":"2025-05-31T10:13:14.517123Z","shell.execute_reply.started":"2025-05-31T10:11:52.211988Z","shell.execute_reply":"2025-05-31T10:13:14.516277Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"seq_subject_map = train.groupby(\"sequence_id\")[\"subject\"].first().value_counts()\nseq_subject_map.plot(kind='bar', figsize=(12, 5), title=\"Number of Sequences per Subject\")\nplt.xlabel(\"Subject\")\nplt.ylabel(\"Sequence Count\")\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:14.518603Z","iopub.execute_input":"2025-05-31T10:13:14.519543Z","iopub.status.idle":"2025-05-31T10:13:15.707537Z","shell.execute_reply.started":"2025-05-31T10:13:14.519513Z","shell.execute_reply":"2025-05-31T10:13:15.706456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.cluster import KMeans\nfrom sklearn.preprocessing import StandardScaler\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# Select features and replace NaN values with column means\nX = agg_features.drop([\"sequence_id\", \"gesture\"], axis=1)\nX_filled = X.fillna(X.mean())\n\n# Standardize the features\nscaler = StandardScaler()\nX_scaled = scaler.fit_transform(X_filled)\n\n# Apply KMeans clustering\nkmeans = KMeans(n_clusters=8, random_state=42)\nagg_features['cluster'] = kmeans.fit_predict(X_scaled)\n\n# Visualize first four features\nsns.pairplot(agg_features, hue='cluster', vars=X.columns[:4])\nplt.suptitle(\"Clustering of Sequences Using KMeans\", y=1.02)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:15.708489Z","iopub.execute_input":"2025-05-31T10:13:15.708775Z","iopub.status.idle":"2025-05-31T10:13:29.127353Z","shell.execute_reply.started":"2025-05-31T10:13:15.708748Z","shell.execute_reply":"2025-05-31T10:13:29.126136Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"example_sequence = train[train[\"sequence_id\"] == train[\"sequence_id\"].unique()[0]]\n\nfig, axs = plt.subplots(4, 1, figsize=(15, 10), sharex=True)\n\naxs[0].plot(example_sequence[\"acc_x\"], label=\"acc_x\")\naxs[0].plot(example_sequence[\"acc_y\"], label=\"acc_y\")\naxs[0].plot(example_sequence[\"acc_z\"], label=\"acc_z\")\naxs[0].set_title(\"IMU - Accelerometer\")\naxs[0].legend()\n\naxs[1].plot(example_sequence[\"rot_x\"], label=\"rot_x\")\naxs[1].plot(example_sequence[\"rot_y\"], label=\"rot_y\")\naxs[1].plot(example_sequence[\"rot_z\"], label=\"rot_z\")\naxs[1].set_title(\"IMU - Rotation\")\naxs[1].legend()\n\naxs[2].plot(example_sequence[[\"thm_1\", \"thm_2\", \"thm_3\", \"thm_4\", \"thm_5\"]])\naxs[2].set_title(\"Thermopile Sensors\")\n\naxs[3].imshow(\n    example_sequence[[f\"tof_1_v{i}\" for i in range(64)]].values.T,\n    aspect='auto', cmap='viridis', interpolation='none'\n)\naxs[3].set_title(\"Time-of-Flight Sensor 1 - 8x8 Grid Over Time\")\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:29.129164Z","iopub.execute_input":"2025-05-31T10:13:29.129645Z","iopub.status.idle":"2025-05-31T10:13:30.148766Z","shell.execute_reply.started":"2025-05-31T10:13:29.129623Z","shell.execute_reply":"2025-05-31T10:13:30.147869Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\n\n# Calculate mean per phase per feature\nphase_summary = train.groupby('behavior')[['acc_x', 'acc_y', 'acc_z', 'thm_1', 'tof_1_v0']].mean().reset_index()\n\n# Melt for easier plotting\nphase_melted = phase_summary.melt(id_vars='behavior', var_name='feature', value_name='mean_value')\n\nplt.figure(figsize=(10, 6))\nsns.barplot(data=phase_melted, x='feature', y='mean_value', hue='behavior')\nplt.title(\"Sensor Mean per Feature by Behavior Phase\")\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:30.149940Z","iopub.execute_input":"2025-05-31T10:13:30.150253Z","iopub.status.idle":"2025-05-31T10:13:30.569291Z","shell.execute_reply.started":"2025-05-31T10:13:30.150229Z","shell.execute_reply":"2025-05-31T10:13:30.568331Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import random\n\n# Pick a random sequence\nseq_id = random.choice(train['sequence_id'].unique())\ndf_seq = train[train['sequence_id'] == seq_id]\n\n# Plot time-series for a few key sensors\nplt.figure(figsize=(14, 5))\nfor col in ['acc_x', 'acc_y', 'acc_z']:\n    plt.plot(df_seq['sequence_counter'], df_seq[col], label=col)\n\nplt.title(f\"Accelerometer Signals for Sequence {seq_id} ({df_seq['behavior'].iloc[-1]})\")\nplt.xlabel(\"Time (sequence_counter)\")\nplt.ylabel(\"Acceleration\")\nplt.legend()\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:30.570186Z","iopub.execute_input":"2025-05-31T10:13:30.570429Z","iopub.status.idle":"2025-05-31T10:13:31.016867Z","shell.execute_reply.started":"2025-05-31T10:13:30.570411Z","shell.execute_reply":"2025-05-31T10:13:31.015938Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestClassifier\nfrom sklearn.impute import SimpleImputer\n\n# Prepare training data\nX = agg_features.drop([\"sequence_id\", \"gesture\"], axis=1)\ny = agg_features[\"gesture\"]\nX = X.fillna(X.mean())\n\n# Train classifier\nrf = RandomForestClassifier(n_estimators=100, random_state=42)\nrf.fit(X, y)\n\n# Plot top features\nimportances = pd.Series(rf.feature_importances_, index=X.columns)\ntop_features = importances.sort_values(ascending=False).head(10)\n\nplt.figure(figsize=(8, 5))\ntop_features.plot(kind='barh')\nplt.title(\"Top 10 Important Features (Random Forest)\")\nplt.gca().invert_yaxis()\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:31.018060Z","iopub.execute_input":"2025-05-31T10:13:31.018411Z","iopub.status.idle":"2025-05-31T10:13:34.897570Z","shell.execute_reply.started":"2025-05-31T10:13:31.018382Z","shell.execute_reply":"2025-05-31T10:13:34.896602Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\n\nsensor_groups = {\n    'IMU only': ['acc_x', 'acc_y', 'acc_z', 'rot_x', 'rot_y', 'rot_z'],\n    'Thermopiles': ['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5'],\n    'ToF avg': [f\"tof_{i}_v{j}\" for i in range(1, 6) for j in range(64)]\n}\n\n# Compute average per sensor (ToF is dense)\nagg_features_tof = train.groupby(\"sequence_id\").agg({\n    **{col: 'mean' for col in train.columns if \"tof\" in col}\n}).reset_index()\nagg_features = agg_features.merge(agg_features_tof, on=\"sequence_id\", how='left')\n\nfor name, cols in sensor_groups.items():\n    cols_existing = [col for col in cols if col in agg_features.columns]\n    X = agg_features[cols_existing].fillna(0)\n    y = agg_features[\"gesture\"]\n\n    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n    clf = RandomForestClassifier(random_state=42)\n    clf.fit(X_train, y_train)\n    print(f\"\\n{name} Only:\")\n    print(classification_report(y_test, clf.predict(X_test)))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:34.898577Z","iopub.execute_input":"2025-05-31T10:13:34.898919Z","iopub.status.idle":"2025-05-31T10:13:53.755037Z","shell.execute_reply.started":"2025-05-31T10:13:34.898870Z","shell.execute_reply":"2025-05-31T10:13:53.754217Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Gesture Specific EDA\n","metadata":{}},{"cell_type":"code","source":"print(train[\"gesture\"].dropna().unique())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:13:53.755905Z","iopub.execute_input":"2025-05-31T10:13:53.756125Z","iopub.status.idle":"2025-05-31T10:13:53.829151Z","shell.execute_reply.started":"2025-05-31T10:13:53.756107Z","shell.execute_reply":"2025-05-31T10:13:53.828228Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Clean whitespace just in case\ntrain[\"gesture\"] = train[\"gesture\"].str.strip()\n\n# Define gestures for comparison\ntarget_gesture = \"Above ear - pull hair\"\nnon_target_gesture = \"Glasses on/off\"\n\n# Filter rows for the two gestures\ndf_target = train[train[\"gesture\"] == target_gesture]\ndf_non_target = train[train[\"gesture\"] == non_target_gesture]\n\n# Print basic info\nprint(\"Target gesture sequences:\", df_target[\"sequence_id\"].nunique())\nprint(\"Non-target gesture sequences:\", df_non_target[\"sequence_id\"].nunique())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:16:30.594555Z","iopub.execute_input":"2025-05-31T10:16:30.595077Z","iopub.status.idle":"2025-05-31T10:16:30.840507Z","shell.execute_reply.started":"2025-05-31T10:16:30.595039Z","shell.execute_reply":"2025-05-31T10:16:30.839652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\n\nfeatures_to_compare = ['acc_x', 'acc_y', 'acc_z', 'rot_x', 'rot_y', 'rot_z']\n\nfor feature in features_to_compare:\n    plt.figure(figsize=(8, 4))\n    sns.histplot(data=df_target, x=feature, hue=\"gesture\", element=\"step\", stat=\"density\", common_norm=False)\n    plt.title(f\"Distribution of {feature} by Gesture\")\n    plt.tight_layout()\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:16:43.558132Z","iopub.execute_input":"2025-05-31T10:16:43.558966Z","iopub.status.idle":"2025-05-31T10:16:45.817316Z","shell.execute_reply.started":"2025-05-31T10:16:43.558943Z","shell.execute_reply":"2025-05-31T10:16:45.816393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Select gestures to compare\ntarget_gesture = \"Above ear - pull hair\"\nnon_target_gesture = \"Glasses on/off\"\n\n# Ensure consistent whitespace handling\ntrain[\"gesture\"] = train[\"gesture\"].str.strip()\n\n# Filter the DataFrame for selected gestures\ndf_target = train[train[\"gesture\"] == target_gesture]\ndf_non_target = train[train[\"gesture\"] == non_target_gesture]\n\n# Plot acceleration comparison across gestures\nplt.figure(figsize=(16, 6))\nfor i, axis in enumerate(['acc_x', 'acc_y', 'acc_z']):\n    plt.subplot(1, 3, i + 1)\n    sns.kdeplot(df_target[axis], label=target_gesture, fill=True)\n    sns.kdeplot(df_non_target[axis], label=non_target_gesture, fill=True)\n    plt.title(f\"{axis} Distribution\")\n    plt.xlabel(axis)\n    plt.ylabel(\"Density\")\n    plt.legend()\nplt.suptitle(\"Acceleration Comparison Between Gestures\")\nplt.tight_layout(rect=[0, 0, 1, 0.95])\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:18:46.591718Z","iopub.execute_input":"2025-05-31T10:18:46.592816Z","iopub.status.idle":"2025-05-31T10:18:48.804697Z","shell.execute_reply.started":"2025-05-31T10:18:46.592785Z","shell.execute_reply":"2025-05-31T10:18:48.803739Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[['acc_x', 'acc_y', 'acc_z']] = train[['acc_x', 'acc_y', 'acc_z']].fillna(train[['acc_x', 'acc_y', 'acc_z']].mean())\n\n# Compute magnitude of acceleration vector\ntrain['acc_magnitude'] = (train['acc_x']**2 + train['acc_y']**2 + train['acc_z']**2)**0.5\n\n# Aggregate mean acceleration magnitude by gesture\ngesture_acc = train.groupby('gesture')['acc_magnitude'].mean().sort_values(ascending=False).reset_index()\n\n# Plot\nplt.figure(figsize=(12, 6))\nsns.barplot(data=gesture_acc, x='gesture', y='acc_magnitude', palette='viridis')\nplt.xticks(rotation=90)\nplt.title(\"Average Acceleration Magnitude per Gesture\")\nplt.ylabel(\"Mean Acceleration Magnitude\")\nplt.xlabel(\"Gesture\")\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:21:00.220144Z","iopub.execute_input":"2025-05-31T10:21:00.220976Z","iopub.status.idle":"2025-05-31T10:21:00.734731Z","shell.execute_reply.started":"2025-05-31T10:21:00.220938Z","shell.execute_reply":"2025-05-31T10:21:00.733931Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Fill missing values in thermopile sensor columns\nthm_cols = ['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5']\ntrain[thm_cols] = train[thm_cols].fillna(train[thm_cols].mean())\n\n# Compute average temperature across thermopiles\ntrain['thm_avg'] = train[thm_cols].mean(axis=1)\n\n# Group by gesture and calculate mean\ngesture_thm = train.groupby('gesture')['thm_avg'].mean().sort_values(ascending=False).reset_index()\n\n# Plot\nplt.figure(figsize=(12, 6))\nsns.barplot(data=gesture_thm, x='gesture', y='thm_avg', palette='coolwarm')\nplt.xticks(rotation=90)\nplt.title(\"Average Temperature (Thermopiles) per Gesture\")\nplt.ylabel(\"Mean Temperature (°C)\")\nplt.xlabel(\"Gesture\")\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:21:58.267701Z","iopub.execute_input":"2025-05-31T10:21:58.268418Z","iopub.status.idle":"2025-05-31T10:21:58.881564Z","shell.execute_reply.started":"2025-05-31T10:21:58.268394Z","shell.execute_reply":"2025-05-31T10:21:58.880770Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Fill missing values in thermopile sensor columns\nthm_cols = ['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5']\ntrain[thm_cols] = train[thm_cols].fillna(train[thm_cols].mean())\n\n# Compute average temperature across thermopiles\ntrain['thm_avg'] = train[thm_cols].mean(axis=1)\n\n# Group by gesture and calculate mean\ngesture_thm = train.groupby('gesture')['thm_avg'].mean().sort_values(ascending=False).reset_index()\n\n# Plot\nplt.figure(figsize=(12, 6))\nsns.barplot(data=gesture_thm, x='gesture', y='thm_avg', palette='coolwarm')\nplt.xticks(rotation=90)\nplt.title(\"Average Temperature (Thermopiles) per Gesture\")\nplt.ylabel(\"Mean Temperature (°C)\")\nplt.xlabel(\"Gesture\")\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:22:44.970844Z","iopub.execute_input":"2025-05-31T10:22:44.971795Z","iopub.status.idle":"2025-05-31T10:22:45.601583Z","shell.execute_reply.started":"2025-05-31T10:22:44.971768Z","shell.execute_reply":"2025-05-31T10:22:45.600643Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Compute phase-wise means\ntrain['thm_avg'] = train[['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5']].mean(axis=1)\ntrain['tof_avg'] = train[tof_cols].mean(axis=1)\n\n# Melt for plotting\nmelted = train.melt(id_vars=['behavior'], value_vars=['thm_avg', 'tof_avg'], var_name='Sensor', value_name='Value')\n\nplt.figure(figsize=(10, 6))\nsns.boxplot(data=melted, x='behavior', y='Value', hue='Sensor')\nplt.title(\"Sensor Readings by Sequence Phase (Behavior)\")\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-31T10:24:32.330836Z","iopub.execute_input":"2025-05-31T10:24:32.331252Z","iopub.status.idle":"2025-05-31T10:24:36.580785Z","shell.execute_reply.started":"2025-05-31T10:24:32.331225Z","shell.execute_reply":"2025-05-31T10:24:36.579840Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}