{"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":"gpu","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"},{"sourceId":253764240,"sourceType":"kernelVersion"}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Libraries / Packages","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom matplotlib import pyplot as plt\nimport seaborn as sns\nfrom matplotlib.ticker import MaxNLocator\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.mplot3d import Axes3D\nimport os\nimport polars as pl\nimport kaggle_evaluation.cmi_inference_server\nfrom sklearn.metrics import accuracy_score, f1_score\nimport joblib\nfrom scipy.spatial.transform import Rotation as R","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:21.340627Z","iopub.execute_input":"2025-08-02T16:41:21.340791Z","iopub.status.idle":"2025-08-02T16:41:24.661835Z","shell.execute_reply.started":"2025-08-02T16:41:21.340770Z","shell.execute_reply":"2025-08-02T16:41:24.661047Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#  Load Data","metadata":{}},{"cell_type":"code","source":"train_pl = pl.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv')\ntrain_demo_pl = pl.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/train_demographics.csv')\ntrain = train_pl.to_pandas()\ntrain_demo = train_demo_pl.to_pandas()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:24.663564Z","iopub.execute_input":"2025-08-02T16:41:24.664246Z","iopub.status.idle":"2025-08-02T16:41:37.476830Z","shell.execute_reply.started":"2025-08-02T16:41:24.664218Z","shell.execute_reply":"2025-08-02T16:41:37.476125Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:37.477730Z","iopub.execute_input":"2025-08-02T16:41:37.477948Z","iopub.status.idle":"2025-08-02T16:41:37.508310Z","shell.execute_reply.started":"2025-08-02T16:41:37.477932Z","shell.execute_reply":"2025-08-02T16:41:37.507594Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Exploratory Data Analysis","metadata":{}},{"cell_type":"code","source":"train.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:37.509276Z","iopub.execute_input":"2025-08-02T16:41:37.509485Z","iopub.status.idle":"2025-08-02T16:41:37.538268Z","shell.execute_reply.started":"2025-08-02T16:41:37.509469Z","shell.execute_reply":"2025-08-02T16:41:37.537586Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:37.538907Z","iopub.execute_input":"2025-08-02T16:41:37.539085Z","iopub.status.idle":"2025-08-02T16:41:43.974232Z","shell.execute_reply.started":"2025-08-02T16:41:37.539070Z","shell.execute_reply":"2025-08-02T16:41:43.973578Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":" # Gesture (Target Column)\n","metadata":{}},{"cell_type":"code","source":"gesture_counts = train['gesture'].value_counts()\n\n# Calculate percentages\npercentages = (gesture_counts / gesture_counts.sum()) * 100\n\n# Create labels with both value counts and percentages\nlabels = [f'{label} ({count}, {perc:.1f}%)' for label, count, perc in zip(gesture_counts.index, gesture_counts.values, percentages)]\n\n# Create the pie chart\nplt.figure(figsize=(8, 8)) # Set figure size for better readability\nplt.pie(gesture_counts, labels=labels, startangle=160, counterclock=False, wedgeprops={'edgecolor': 'black'})\nplt.title('Distribution of Gestures')\nplt.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:43.975008Z","iopub.execute_input":"2025-08-02T16:41:43.975322Z","iopub.status.idle":"2025-08-02T16:41:44.394296Z","shell.execute_reply.started":"2025-08-02T16:41:43.975293Z","shell.execute_reply":"2025-08-02T16:41:44.393546Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Định hướng","metadata":{}},{"cell_type":"code","source":"# Donut Chart\nfig, ax = plt.subplots(figsize=(8, 8))\n\n# Calculate percentages for labels (optional, can also use autopct)\norientation_counts = train[\"orientation\"].value_counts().head()\ntotal_count = orientation_counts.sum()\nlabels = [f'{label} ({count})' for label, count in orientation_counts.items()]\n\nwedges, texts, autotexts = ax.pie(\n    orientation_counts,\n    autopct='%1.1f%%',\n    startangle=90,\n    colors=plt.cm.Paired.colors,\n    pctdistance=0.85, # Distance of the percentage labels from the center\n    wedgeprops=dict(width=0.3, edgecolor='w'), # Create the donut hole\n    labels=labels\n)\n\n# Draw a circle in the middle to make it a donut chart\ncentre_circle = plt.Circle((0,0), 0.70, fc='white')\nfig.gca().add_artist(centre_circle)\n\nax.set_title(\"Subject's orientation (Donut Chart)\")\nax.axis('equal')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:44.396465Z","iopub.execute_input":"2025-08-02T16:41:44.396697Z","iopub.status.idle":"2025-08-02T16:41:44.549537Z","shell.execute_reply.started":"2025-08-02T16:41:44.396670Z","shell.execute_reply":"2025-08-02T16:41:44.548816Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Vertical Bar Chart\nfig, ax = plt.subplots(figsize=(8, 6))\norientation_counts.sort_values(ascending=False).plot( # Often good to sort descending for vertical bars\n    kind=\"bar\", color='purple', ax=ax, title=\"Target (Vertical Bar)\"\n)\nax.set_xlabel(\"Target\")\nax.set_ylabel(\"Count\")\nplt.xticks(rotation=20, ha='right') # Rotate x-axis labels for better readability if they overlap\nplt.tight_layout() # Adjust layout to prevent labels from overlapping\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:44.550333Z","iopub.execute_input":"2025-08-02T16:41:44.550608Z","iopub.status.idle":"2025-08-02T16:41:44.760313Z","shell.execute_reply.started":"2025-08-02T16:41:44.550589Z","shell.execute_reply":"2025-08-02T16:41:44.759495Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Sequence Type (Target vs Non Target)\n","metadata":{}},{"cell_type":"code","source":"# Donut Chart\nfig, ax = plt.subplots(figsize=(8, 8))\n\n# Calculate percentages for labels (optional, can also use autopct)\nsequence_type_counts = train[\"sequence_type\"].value_counts().head()\ntotal_count = sequence_type_counts.sum()\nlabels = [f'{label} ({count})' for label, count in sequence_type_counts.items()]\n\nwedges, texts, autotexts = ax.pie(\n    sequence_type_counts,\n    autopct='%1.1f%%',\n    startangle=90,\n    colors=plt.cm.Paired.colors,\n    pctdistance=0.85, # Distance of the percentage labels from the center\n    wedgeprops=dict(width=0.3, edgecolor='w'), # Create the donut hole\n    labels=labels\n)\n\n# Draw a circle in the middle to make it a donut chart\ncentre_circle = plt.Circle((0,0), 0.70, fc='white')\nfig.gca().add_artist(centre_circle)\n\nax.set_title(\"Target vs Non-target (Donut Chart)\")\nax.axis('equal')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:44.761190Z","iopub.execute_input":"2025-08-02T16:41:44.761460Z","iopub.status.idle":"2025-08-02T16:41:44.901293Z","shell.execute_reply.started":"2025-08-02T16:41:44.761436Z","shell.execute_reply":"2025-08-02T16:41:44.900352Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Vertical Bar Chart\nfig, ax = plt.subplots(figsize=(8, 6))\nsequence_type_counts.sort_values(ascending=False).plot( # Often good to sort descending for vertical bars\n    kind=\"bar\", color='lightgreen', ax=ax, title=\"Target vs Non Target (Vertical Bar)\"\n)\nax.set_xlabel(\"Target\")\nax.set_ylabel(\"Count\")\nplt.xticks(rotation=20, ha='right') # Rotate x-axis labels for better readability if they overlap\nplt.tight_layout() # Adjust layout to prevent labels from overlapping\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:44.902052Z","iopub.execute_input":"2025-08-02T16:41:44.902419Z","iopub.status.idle":"2025-08-02T16:41:45.055879Z","shell.execute_reply.started":"2025-08-02T16:41:44.902400Z","shell.execute_reply":"2025-08-02T16:41:45.055200Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Behavior","metadata":{}},{"cell_type":"code","source":"# Donut Chart\nfig, ax = plt.subplots(figsize=(8, 8))\n\n# Calculate percentages for labels (optional, can also use autopct)\nbehavior_counts = train[\"behavior\"].value_counts().head()\ntotal_count = behavior_counts.sum()\nlabels = [f'{label} ({count})' for label, count in behavior_counts.items()]\n\nwedges, texts, autotexts = ax.pie(\n    behavior_counts,\n    autopct='%1.1f%%',\n    startangle=90,\n    colors=plt.cm.Paired.colors,\n    pctdistance=0.85, # Distance of the percentage labels from the center\n    wedgeprops=dict(width=0.3, edgecolor='w'), # Create the donut hole\n    labels=labels\n)\n\n# Draw a circle in the middle to make it a donut chart\ncentre_circle = plt.Circle((0,0), 0.70, fc='white')\nfig.gca().add_artist(centre_circle)\n\nax.set_title(\"Subject's Behavior During the Sequence (Donut Chart)\")\nax.axis('equal')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:45.056676Z","iopub.execute_input":"2025-08-02T16:41:45.057005Z","iopub.status.idle":"2025-08-02T16:41:45.225463Z","shell.execute_reply.started":"2025-08-02T16:41:45.056978Z","shell.execute_reply":"2025-08-02T16:41:45.224415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Vertical Bar Chart\nfig, ax = plt.subplots(figsize=(8, 6))\nbehavior_counts.sort_values(ascending=False).plot( # Often good to sort descending for vertical bars\n    kind=\"bar\", color='skyblue', ax=ax, title=\"Subject's Behavior During the Sequence (Vertical Bar)\"\n)\nax.set_xlabel(\"Behavior\")\nax.set_ylabel(\"Count\")\nplt.xticks(rotation=20, ha='right') # Rotate x-axis labels for better readability if they overlap\nplt.tight_layout() # Adjust layout to prevent labels from overlapping\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:45.226386Z","iopub.execute_input":"2025-08-02T16:41:45.226606Z","iopub.status.idle":"2025-08-02T16:41:45.389855Z","shell.execute_reply.started":"2025-08-02T16:41:45.226590Z","shell.execute_reply":"2025-08-02T16:41:45.388962Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Demographics Correlation Matrix","metadata":{}},{"cell_type":"code","source":"# correlation matrix\nplt.figure(figsize = (8, 4))\nsns.heatmap(data = train_demo.corr(numeric_only = True), linewidth = 0.5, annot = True, linecolor = \"black\")\nplt.title('Train Data Demographic Correlation Heatmap')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:45.390638Z","iopub.execute_input":"2025-08-02T16:41:45.390972Z","iopub.status.idle":"2025-08-02T16:41:45.661317Z","shell.execute_reply.started":"2025-08-02T16:41:45.390950Z","shell.execute_reply":"2025-08-02T16:41:45.660550Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Gender Distribution","metadata":{}},{"cell_type":"code","source":"# Get value counts for gender\nvc = train_demo['sex'].value_counts()\n\n# Extract counts (assuming 'count' column doesn't exist)\ncounts = vc.values\n\n# Create labels (assuming 'count' column doesn't exist)\nlabels = ['Male', 'Female']  # Assuming 'Male' maps to '1' and 'Female' to '0'\n\n# Plot the pie chart\nplt.pie(counts, labels=labels, autopct=\"%1.1f%%\")  # Add percentages to pie slices\nplt.title('Gender')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:45.662139Z","iopub.execute_input":"2025-08-02T16:41:45.662402Z","iopub.status.idle":"2025-08-02T16:41:45.734136Z","shell.execute_reply.started":"2025-08-02T16:41:45.662384Z","shell.execute_reply":"2025-08-02T16:41:45.733431Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Age Distribution with respect to Gender","metadata":{}},{"cell_type":"code","source":"#'train' is DataFrame\n_, axs = plt.subplots(2, 1, sharex=True)\n\nfor sex in range(2):\n  ax = axs.ravel()[sex]\n\n  # Filter by sex using boolean indexing\n  sex_filter = train_demo['sex'] == sex\n  vc = train_demo[sex_filter]['age'].value_counts()  # Access column after filtering\n\n  # Plot the bar chart\n  ax.bar(vc.index, vc.values, color=['lightblue', 'coral'][sex], label=['Male', 'Female'][sex])\n  ax.xaxis.set_major_locator(MaxNLocator(integer=True))\n  ax.set_ylabel('count')\n  ax.legend()\n\nplt.suptitle('Age distribution with respect to Gender')\naxs.ravel()[1].set_xlabel('years')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:45.734828Z","iopub.execute_input":"2025-08-02T16:41:45.735018Z","iopub.status.idle":"2025-08-02T16:41:46.006922Z","shell.execute_reply.started":"2025-08-02T16:41:45.735004Z","shell.execute_reply":"2025-08-02T16:41:46.006179Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Linear Acceleration from IMU Sensor","metadata":{}},{"cell_type":"code","source":"\n# Initialize the 3D plot\nfig = plt.figure(figsize=(10, 10)) # Adjust figure size for better visibility\nax = fig.add_subplot(111, projection='3d')\n\n# Get unique values from the 'gesture' column for coloring\nunique_gestures = train['gesture'].unique()\n\n# Use a colormap to get distinct colors for each gesture type\n# matplotlib.colormaps is the recommended way to access colormaps now\ncolors = plt.colormaps['tab10'].resampled(len(unique_gestures)) # 'tab10' is good for categorical data\n\n# Iterate through unique gestures and plot them with different colors\nfor i, gesture_type in enumerate(unique_gestures):\n    subset = train[train['gesture'] == gesture_type]\n    ax.scatter(subset['acc_x'], subset['acc_y'], subset['acc_z'],\n               color=colors(i),    # Assign a unique color from the colormap\n               label=gesture_type, # Label for the legend\n               alpha=0.7,          # Opacity (matches your Plotly opacity)\n               s=2,\n               rasterized=True)                # Size of points (similar to Plotly's size_max=1, adjusted for visibility)\n\n# Set labels and title\nax.set_xlabel('acc_x', fontsize=14)\nax.set_ylabel('acc_y', fontsize=14)\nax.set_zlabel('acc_z', fontsize=14)\nax.set_title('Linear acceleration along X, Y, Z axes', fontsize=16)\n\n# Add a legend to differentiate 'gesture' types\nax.legend(title='Gesture Type', fontsize=10, title_fontsize=12, loc='upper right')\n\n# Set tick label font size\nax.tick_params(axis='both', which='major', labelsize=12)\n\n# --- Mimic Plotly's 'plotly_dark' template ---\n# Set the background color of the plot\nax.set_facecolor('black')\n\n# Make the pane background transparent\nax.xaxis.pane.fill = False\nax.yaxis.pane.fill = False\nax.zaxis.pane.fill = False\n\n# Set the pane edge colors\nax.xaxis.pane.edgecolor = 'grey'\nax.yaxis.pane.edgecolor = 'grey'\nax.zaxis.pane.edgecolor = 'grey'\n\n# Set the actual pane face colors to transparent\nax.xaxis.pane.set_facecolor((0.0, 0.0, 0.0, 0.0))\nax.yaxis.pane.set_facecolor((0.0, 0.0, 0.0, 0.0))\nax.zaxis.pane.set_facecolor((0.0, 0.0, 0.0, 0.0))\n\n# Set grid lines color\nax.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.5)\n\nplt.tight_layout() # Adjust layout to prevent labels from overlapping\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:46.008339Z","iopub.execute_input":"2025-08-02T16:41:46.008617Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"3D Scatter plot shows linear accelartion along x, y and z axes. Color acts as the fourth dimension and differenciates different points based on the target column i.e gesture. ","metadata":{}},{"cell_type":"code","source":"# Initialize the 3D plot\nfig = plt.figure(figsize=(10, 10)) # Adjust figure size for better visibility\nax = fig.add_subplot(111, projection='3d')\n\n# Get unique values from 'sequence_type' for coloring\nunique_sequence_types = train['sequence_type'].unique()\n\n# --- ADDRESSING DEPRECATION WARNING 1: get_cmap ---\n# Use matplotlib.colormaps[name] instead of plt.cm.get_cmap(name)\ncolors = plt.colormaps['viridis'].resampled(len(unique_sequence_types))\n\n# Iterate through unique sequence types and plot them with different colors\nfor i, seq_type in enumerate(unique_sequence_types):\n    subset = train[train['sequence_type'] == seq_type]\n    ax.scatter(subset['acc_x'], subset['acc_y'], subset['acc_z'],\n               color=colors(i), # Assign a unique color\n               label=seq_type,  # Label for the legend\n               alpha=0.7,       # Opacity\n               s=10)            # Size of points (similar to Plotly's size_max)\n\n# Set labels and title\nax.set_xlabel('acc_x', fontsize=14)\nax.set_ylabel('acc_y', fontsize=14)\nax.set_zlabel('acc_z', fontsize=14)\nax.set_title('Linear acceleration along X, Y, Z axes', fontsize=16)\n\n# Add a legend to differentiate 'sequence_type'\nax.legend(title='Sequence Type', fontsize=12, title_fontsize=14)\n\n# Set tick label font size\nax.tick_params(axis='both', which='major', labelsize=12)\n\n# Set background color to dark and adjust grid/pane colors\nax.set_facecolor('black')\n\n# --- ADDRESSING DEPRECATION WARNINGS 2, 3, 4: w_xaxis, w_yaxis, w_zaxis ---\n# Use .xaxis, .yaxis, .zaxis directly for panes\nax.xaxis.pane.fill = False\nax.yaxis.pane.fill = False\nax.zaxis.pane.fill = False\n\nax.xaxis.pane.edgecolor = 'grey'\nax.yaxis.pane.edgecolor = 'grey'\nax.zaxis.pane.edgecolor = 'grey'\n\n# Set pane colors to transparent for a truly dark effect\n# These are now accessed directly through .xaxis.pane.set_facecolor\nax.xaxis.pane.set_facecolor((0.0, 0.0, 0.0, 0.0))\nax.yaxis.pane.set_facecolor((0.0, 0.0, 0.0, 0.0))\nax.zaxis.pane.set_facecolor((0.0, 0.0, 0.0, 0.0))\n\nax.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.5)\n\nplt.tight_layout() # Adjust layout to prevent labels from overlapping\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:41:54.615683Z","iopub.execute_input":"2025-08-02T16:41:54.616202Z","iopub.status.idle":"2025-08-02T16:42:05.547667Z","shell.execute_reply.started":"2025-08-02T16:41:54.616179Z","shell.execute_reply":"2025-08-02T16:42:05.546982Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"3D Scatter plot shows linear accelartion along x, y and z axes. Color acts as the fourth dimension and differenciates points based on sequence_type column i.e target and non-target. ","metadata":{}},{"cell_type":"markdown","source":"# Rotation of Gyroscope from IMU Sensor","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(14, 8)) # Adjust figure size as needed\nax = fig.add_subplot(111, projection='3d')\n\n# Plot the 3D line\n# For color, matplotlib's plot3D doesn't directly support a continuous 'color'\n# argument like px.line_3d. You'd typically use a colormap and map 'rot_w' to it.\n# This example uses a simple line color. For continuous color, you'd need\n# to segment your data or use scatter3D with c=train['rot_w'].\n# ax.plot(train['rot_x'], train['rot_y'], train['rot_z'], color='skyblue', linewidth=0.5)\n\n# If you want to color by 'rot_w' with a gradient, it's often better to use scatter3D\n# if a continuous line isn't strictly necessary, or segment the line.\n# For a true line plot with continuous color, it's more complex in matplotlib.\n# Example for scatter3D with color:\nsc = ax.scatter(train['rot_x'], train['rot_y'], train['rot_z'], c=train['rot_w'], cmap='viridis', s=1)\nfig.colorbar(sc, ax=ax, label='rot_w')\n\n\nax.set_xlabel('rot_x')\nax.set_ylabel('rot_y')\nax.set_zlabel('rot_z')\nax.set_title('3D Path of Gyroscope Rotation Over Time')\n\n# Adjust font sizes if needed (similar to update_layout in Plotly)\nax.tick_params(axis='both', which='major', labelsize=12)\nax.xaxis.label.set_size(14)\nax.yaxis.label.set_size(14)\nax.zaxis.label.set_size(14)\nax.title.set_size(16)\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:42:05.548644Z","iopub.execute_input":"2025-08-02T16:42:05.548834Z","iopub.status.idle":"2025-08-02T16:42:12.214524Z","shell.execute_reply.started":"2025-08-02T16:42:05.548820Z","shell.execute_reply":"2025-08-02T16:42:12.213792Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Temperature from Thermopile of IMU Sensors","metadata":{}},{"cell_type":"code","source":"# Melt the DataFrame for easier plotting\ndf_melted = train.melt(id_vars='sequence_type', \n                    value_vars=['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5'],\n                    var_name='sensor', \n                    value_name='temperature')\n\n# Plot\nplt.figure(figsize=(10, 6))\nsns.boxplot(x='sequence_type', y='temperature', hue='sensor', data=df_melted)\nplt.title('Thermopile Sensor Readings by Sequence Type')\nplt.xlabel('Sequence Type')\nplt.ylabel('Temperature (°C)')\nplt.legend(title='Sensor')\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:42:12.215366Z","iopub.execute_input":"2025-08-02T16:42:12.215580Z","iopub.status.idle":"2025-08-02T16:42:15.366461Z","shell.execute_reply.started":"2025-08-02T16:42:12.215564Z","shell.execute_reply":"2025-08-02T16:42:15.365604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Group by sequence_type and get mean values\ndf_grouped = train.groupby('sequence_type')[['thm_1','thm_2','thm_3','thm_4','thm_5']].mean()\n\ncategories = ['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5']\nN = len(categories)\n\nangles = [n / float(N) * 2 * np.pi for n in range(N)]\nangles += angles[:1]  # Close the loop\n\nfig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))\n\nfor idx, row in df_grouped.iterrows():\n    values = row.values.tolist()\n    values += values[:1]  # Close the loop\n    ax.plot(angles, values, marker='o', label=idx)\n    ax.fill(angles, values, alpha=0.1)\n\nax.set_xticks(angles[:-1])\nax.set_xticklabels(categories)\nplt.legend(title=\"Sequence Type\")\nplt.title(\"Radar Chart of Average Thermopile Readings by Sequence Type\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:42:15.367141Z","iopub.execute_input":"2025-08-02T16:42:15.367335Z","iopub.status.idle":"2025-08-02T16:42:15.657367Z","shell.execute_reply.started":"2025-08-02T16:42:15.367321Z","shell.execute_reply":"2025-08-02T16:42:15.656637Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"By analyzing the Boxplot and Radar Chart above we can say that temperature for target is slightly higher than non-target.\nNext lets see box plot of thermopile values against column gesture and column behavior.","metadata":{}},{"cell_type":"code","source":"# Melt the DataFrame for easier plotting\ndf_melted = train.melt(id_vars='gesture', \n                    value_vars=['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5'],\n                    var_name='sensor', \n                    value_name='temperature')\n\n# Plot\nplt.figure(figsize=(10, 6))\nsns.boxplot(x='gesture', y='temperature', hue='sensor', data=df_melted)\nplt.title('Thermopile Sensor Readings by Gesture')\nplt.xlabel('Gesture')\nplt.ylabel('Temperature (°C)')\nplt.legend(title='Sensor')\nplt.xticks(rotation=90)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:42:15.658257Z","iopub.execute_input":"2025-08-02T16:42:15.658484Z","iopub.status.idle":"2025-08-02T16:42:20.793598Z","shell.execute_reply.started":"2025-08-02T16:42:15.658463Z","shell.execute_reply":"2025-08-02T16:42:20.792933Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Melt the DataFrame for easier plotting\ndf_melted = train.melt(id_vars='behavior', \n                    value_vars=['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5'],\n                    var_name='sensor', \n                    value_name='temperature')\n\n# Plot\nplt.figure(figsize=(10, 6))\nsns.boxplot(x='behavior', y='temperature', hue='sensor', data=df_melted)\nplt.title('Thermopile Sensor Readings by Behavior')\nplt.xlabel('Behavior')\nplt.ylabel('Temperature (°C)')\nplt.legend(title='Sensor')\nplt.xticks(rotation=25)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:42:20.796782Z","iopub.execute_input":"2025-08-02T16:42:20.797394Z","iopub.status.idle":"2025-08-02T16:42:24.207623Z","shell.execute_reply.started":"2025-08-02T16:42:20.797367Z","shell.execute_reply":"2025-08-02T16:42:24.206916Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Null Percentage","metadata":{}},{"cell_type":"code","source":"def null_percent(df):\n    per=((df.isnull().sum()/len(df))*100).round(2)\n    return per[per>0]\n\nprint(\"Nan Values in Train data\")\nprint(null_percent(train))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T16:42:24.208521Z","iopub.execute_input":"2025-08-02T16:42:24.208814Z","iopub.status.idle":"2025-08-02T16:42:24.988933Z","shell.execute_reply.started":"2025-08-02T16:42:24.208781Z","shell.execute_reply":"2025-08-02T16:42:24.988116Z"}},"outputs":[],"execution_count":null}]}