{ "cells": [ { "cell_type": "code", "execution_count": 2, "id": "2ac958fd", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Heel stack lab Heel stack brandForefoot lab Forefoot brandWidths availableFor heavy runnersSeasonRemovable insoleOrthotic friendlyWaterproofingRankingPopularity
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/forefoot...30.6 mm 38.0 mm30.3 mm 30.0 mmNormal0All seasons11-#67 Top 19%#163 Top 45%
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelMid/forefoot...32.8 mm 26.0 mm24.6 mm 18.0 mmNormal0-11-#45 Top 13%#294 Bottom 20%
2AltraExperience Wild88\\n Great!$145LightModerateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/forefoot...34.5 mm 34.0 mm30.2 mm 30.0 mmNormal0All seasons11-#251 Top 39%#308 Top 48%
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/forefoot...32.3 mm 32.0 mm26.2 mm 28.0 mmNormal0All seasons11-#315 Bottom 14%#211 Bottom 42%
4AltraLone Peak 5.091\\n Superb!$130LightModerateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/forefoot...24.5 mm 25.0 mm24.3 mm 25.0 mmNormal0-11-#62 Top 10%#63 Top 10%
\n", "

5 rows × 33 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 LightModerate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 LightModerate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... Heel stack lab Heel stack brand \\\n", "0 Mid/forefoot ... 30.6 mm 38.0 mm \n", "1 HeelMid/forefoot ... 32.8 mm 26.0 mm \n", "2 Mid/forefoot ... 34.5 mm 34.0 mm \n", "3 Mid/forefoot ... 32.3 mm 32.0 mm \n", "4 Mid/forefoot ... 24.5 mm 25.0 mm \n", "\n", " Forefoot lab Forefoot brand Widths available For heavy runners Season \\\n", "0 30.3 mm 30.0 mm Normal 0 All seasons \n", "1 24.6 mm 18.0 mm Normal 0 - \n", "2 30.2 mm 30.0 mm Normal 0 All seasons \n", "3 26.2 mm 28.0 mm Normal 0 All seasons \n", "4 24.3 mm 25.0 mm Normal 0 - \n", "\n", " Removable insole Orthotic friendly Waterproofing Ranking \\\n", "0 1 1 - #67 Top 19% \n", "1 1 1 - #45 Top 13% \n", "2 1 1 - #251 Top 39% \n", "3 1 1 - #315 Bottom 14% \n", "4 1 1 - #62 Top 10% \n", "\n", " Popularity \n", "0 #163 Top 45% \n", "1 #294 Bottom 20% \n", "2 #308 Top 48% \n", "3 #211 Bottom 42% \n", "4 #63 Top 10% \n", "\n", "[5 rows x 33 columns]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "df = pd.read_csv('../../data/SONIX utilities - Trail.csv')\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 3, "id": "1d5187d2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 498 entries, 0 to 497\n", "Data columns (total 33 columns):\n", " # Column Non-Null Count Dtype\n", "--- ------ -------------- -----\n", " 0 Brand 459 non-null str \n", " 1 Name 460 non-null str \n", " 2 Audience score 458 non-null str \n", " 3 Price 460 non-null str \n", " 4 Trail terrain 460 non-null str \n", " 5 Arch support 461 non-null str \n", " 6 Weight lab Weight brand 461 non-null str \n", " 7 Lightweight 461 non-null str \n", " 8 Drop lab Drop brand 460 non-null str \n", " 9 Strike pattern 460 non-null str \n", " 10 Size 460 non-null str \n", " 11 Midsole softness 460 non-null str \n", " 12 Plate 460 non-null str \n", " 13 Toebox durability 460 non-null str \n", " 14 Heel padding durability 460 non-null str \n", " 15 Outsole durability 460 non-null str \n", " 16 Breathability 460 non-null str \n", " 17 Width / fit 460 non-null str \n", " 18 Toebox width 460 non-null str \n", " 19 Stiffness 460 non-null str \n", " 20 Torsional rigidity 460 non-null str \n", " 21 Heel counter stiffness 460 non-null str \n", " 22 Lug depth 460 non-null str \n", " 23 Heel stack lab Heel stack brand 460 non-null str \n", " 24 Forefoot lab Forefoot brand 460 non-null str \n", " 25 Widths available 460 non-null str \n", " 26 For heavy runners 460 non-null str \n", " 27 Season 460 non-null str \n", " 28 Removable insole 460 non-null str \n", " 29 Orthotic friendly 460 non-null str \n", " 30 Waterproofing 459 non-null str \n", " 31 Ranking 460 non-null str \n", " 32 Popularity 459 non-null str \n", "dtypes: str(33)\n", "memory usage: 128.5 KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 4, "id": "7e52cec2", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Heel stack lab Heel stack brandForefoot lab Forefoot brandWidths availableFor heavy runnersSeasonRemovable insoleOrthotic friendlyWaterproofingRankingPopularity
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/forefoot...30.6 mm 38.0 mm30.3 mm 30.0 mmNormal0All seasons11-#67 Top 19%#163 Top 45%
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelMid/forefoot...32.8 mm 26.0 mm24.6 mm 18.0 mmNormal0-11-#45 Top 13%#294 Bottom 20%
2AltraExperience Wild88\\n Great!$145LightModerateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/forefoot...34.5 mm 34.0 mm30.2 mm 30.0 mmNormal0All seasons11-#251 Top 39%#308 Top 48%
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/forefoot...32.3 mm 32.0 mm26.2 mm 28.0 mmNormal0All seasons11-#315 Bottom 14%#211 Bottom 42%
4AltraLone Peak 5.091\\n Superb!$130LightModerateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/forefoot...24.5 mm 25.0 mm24.3 mm 25.0 mmNormal0-11-#62 Top 10%#63 Top 10%
\n", "

5 rows × 33 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 LightModerate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 LightModerate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... Heel stack lab Heel stack brand \\\n", "0 Mid/forefoot ... 30.6 mm 38.0 mm \n", "1 HeelMid/forefoot ... 32.8 mm 26.0 mm \n", "2 Mid/forefoot ... 34.5 mm 34.0 mm \n", "3 Mid/forefoot ... 32.3 mm 32.0 mm \n", "4 Mid/forefoot ... 24.5 mm 25.0 mm \n", "\n", " Forefoot lab Forefoot brand Widths available For heavy runners Season \\\n", "0 30.3 mm 30.0 mm Normal 0 All seasons \n", "1 24.6 mm 18.0 mm Normal 0 - \n", "2 30.2 mm 30.0 mm Normal 0 All seasons \n", "3 26.2 mm 28.0 mm Normal 0 All seasons \n", "4 24.3 mm 25.0 mm Normal 0 - \n", "\n", " Removable insole Orthotic friendly Waterproofing Ranking \\\n", "0 1 1 - #67 Top 19% \n", "1 1 1 - #45 Top 13% \n", "2 1 1 - #251 Top 39% \n", "3 1 1 - #315 Bottom 14% \n", "4 1 1 - #62 Top 10% \n", "\n", " Popularity \n", "0 #163 Top 45% \n", "1 #294 Bottom 20% \n", "2 #308 Top 48% \n", "3 #211 Bottom 42% \n", "4 #63 Top 10% \n", "\n", "[5 rows x 33 columns]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 5, "id": "8778d8f7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Brand (28 unique)\n", "\n", "[ 'Adidas', 'Altra', 'ASICS', 'Brooks',\n", " 'Hoka', 'HOKA', 'hoka', 'Inov8',\n", " 'KEEN', 'La Sportiva', 'Merrell', 'new Balance',\n", " 'New Balance', 'Nike', 'nike', 'NNormal',\n", " 'On', 'on', 'salomon', 'Salomon',\n", " 'Saucony', 'SAucony', 'Scarpa', 'The North Face',\n", " 'Topo', 'Xero Shoes', 'Kailas', 'Icebug']\n", "Length: 28, dtype: str\n", "\n", "Trail terrain (6 unique)\n", "\n", "[ 'Light', 'LightModerate', 'ModerateTechnical',\n", " 'Moderate', 'Technical', 'Trail terrain']\n", "Length: 6, dtype: str\n", "\n", "Arch support (4 unique)\n", "\n", "['Neutral', 'Stability', 'Shock absorption', 'Arch support']\n", "Length: 4, dtype: str\n", "\n", "Lightweight (4 unique)\n", "\n", "['0', '1', 'Traction', 'Lightweight']\n", "Length: 4, dtype: str\n", "\n", "Strike pattern (4 unique)\n", "\n", "['Mid/forefoot', 'HeelMid/forefoot', 'Heel', 'Strike pattern']\n", "Length: 4, dtype: str\n", "\n", "Size (6 unique)\n", "\n", "[ 'Slightly large', 'True to size', '-', 'Slightly small',\n", " 'Half size small', 'Size']\n", "Length: 6, dtype: str\n", "\n", "Midsole softness (5 unique)\n", "\n", "['Balanced', '-', 'Soft', 'Firm', 'Midsole softness']\n", "Length: 5, dtype: str\n", "\n", "Plate (5 unique)\n", "\n", "[ '0',\n", " 'Rock plate',\n", " 'Carbon plate',\n", " 'Difference in midsole softness in cold',\n", " 'Plate']\n", "Length: 5, dtype: str\n", "\n", "Toebox durability (7 unique)\n", "\n", "['Good', '-', 'Decent', 'Very good', 'Bad', 'Very bad', 'Toebox durability']\n", "Length: 7, dtype: str\n", "\n", "Heel padding durability (5 unique)\n", "\n", "['Good', '-', 'Decent', 'Bad', 'Heel padding durability']\n", "Length: 5, dtype: str\n", "\n", "Outsole durability (5 unique)\n", "\n", "['Decent', '-', 'Good', 'Bad', 'Outsole durability']\n", "Length: 5, dtype: str\n", "\n", "Breathability (5 unique)\n", "\n", "['Moderate', '-', 'Warm', 'Breathable', 'Breathability']\n", "Length: 5, dtype: str\n", "\n", "Width / fit (4 unique)\n", "\n", "['Medium', 'Narrow', 'Wide', 'Width / fit']\n", "Length: 4, dtype: str\n", "\n", "Toebox width (5 unique)\n", "\n", "['Narrow', '-', 'Wide', 'Medium', 'Toebox width']\n", "Length: 5, dtype: str\n", "\n", "Stiffness (4 unique)\n", "\n", "['Moderate', 'Stiff', 'Flexible', 'Stiffness']\n", "Length: 4, dtype: str\n", "\n", "Torsional rigidity (5 unique)\n", "\n", "['Stiff', 'Flexible', 'Moderate', '-', 'Torsional rigidity']\n", "Length: 5, dtype: str\n", "\n", "Heel counter stiffness (5 unique)\n", "\n", "['Flexible', 'Moderate', '-', 'Stiff', 'Heel counter stiffness']\n", "Length: 5, dtype: str\n", "\n", "Waterproofing (5 unique)\n", "\n", "['-', 'Waterproof', 'Water repellent', 'WaterproofWater repellent', 'Ranking']\n", "Length: 5, dtype: str\n", "\n", "Widths available (6 unique)\n", "\n", "[ 'Normal', 'NormalWide', 'NormalWideX-Wide',\n", " 'NarrowNormal', 'Wide', 'Widths available']\n", "Length: 6, dtype: str\n", "\n", "Orthotic friendly (3 unique)\n", "\n", "['1', '0', 'Orthotic friendly']\n", "Length: 3, dtype: str\n", "\n", "For heavy runners (3 unique)\n", "\n", "['0', '1', 'For heavy runners']\n", "Length: 3, dtype: str\n", "\n", "Season (5 unique)\n", "\n", "['All seasons', '-', 'SummerAll seasons', 'Winter', 'Season']\n", "Length: 5, dtype: str\n", "\n", "Removable insole (3 unique)\n", "\n", "['1', '0', 'Removable insole']\n", "Length: 3, dtype: str\n" ] } ], "source": [ "observed_col = [ \n", " 'Brand',\n", " 'Trail terrain',\n", " 'Arch support',\n", " 'Lightweight',\n", " 'Strike pattern',\n", " 'Size', #ini actually sama kaya observed col-nya road \n", " 'Midsole softness',\n", " 'Plate',\n", " 'Toebox durability',\n", " 'Heel padding durability',\n", " 'Outsole durability',\n", " 'Breathability',\n", " 'Width / fit',\n", " 'Toebox width',\n", " 'Stiffness',\n", " 'Torsional rigidity',\n", " 'Heel counter stiffness', \n", " 'Waterproofing',\n", " 'Widths available', # aku mikir ini ga perlu soalnya ini available size, bukan size yang dipake user\n", " 'Orthotic friendly',\n", " 'For heavy runners',\n", " 'Season',\n", " 'Removable insole'\n", "]\n", "\n", "for col in observed_col: \n", " uniques = df[col].dropna().unique()\n", " print(f\"\\n{col} ({len(uniques)} unique)\")\n", " print(uniques)" ] }, { "cell_type": "markdown", "id": "7df7bd0d", "metadata": {}, "source": [ "# Clear duplicate rows" ] }, { "cell_type": "code", "execution_count": 6, "id": "f67e8393", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before: 498\n", "After : 183\n" ] } ], "source": [ "print(\"Before:\", len(df))\n", "df = df.drop_duplicates(subset=[\"Brand\", \"Name\"], keep=\"first\").reset_index(drop=True)\n", "print(\"After :\", len(df))" ] }, { "cell_type": "markdown", "id": "af1f7980", "metadata": {}, "source": [ "# Clearing Brand" ] }, { "cell_type": "code", "execution_count": 8, "id": "f4f07a73", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Brand (21 uniques): \n", " ['Adidas', 'Altra', 'Asics', 'Brooks', 'Hoka', 'Icebug', 'Inov8', 'Kailas', 'Keen', 'La Sportiva', 'Merrell', 'New Balance', 'Nike', 'Nnormal', 'On', 'Salomon', 'Saucony', 'Scarpa', 'The North Face', 'Topo', 'Xero Shoes']\n" ] }, { "data": { "text/plain": [ "Brand\n", "Salomon 26\n", "Hoka 21\n", "Nike 20\n", "Altra 18\n", "New Balance 15\n", "Saucony 13\n", "Brooks 12\n", "Asics 11\n", "Merrell 11\n", "Kailas 10\n", "On 5\n", "Inov8 4\n", "Topo 4\n", "Adidas 2\n", "La Sportiva 2\n", "Xero Shoes 2\n", "Keen 1\n", "Nnormal 1\n", "Scarpa 1\n", "The North Face 1\n", "Icebug 1\n", "Name: count, dtype: int64" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Brand\"] = (\n", " df[\"Brand\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "brand_uniques = df[\"Brand\"].dropna().unique()\n", "# brand_uniques.sort()\n", "brand_uniques = sorted(brand_uniques)\n", "print(f\"Brand ({len(brand_uniques)} uniques): \\n\",brand_uniques)\n", "\n", "df[\"Brand\"].value_counts()" ] }, { "cell_type": "markdown", "id": "f915b663", "metadata": {}, "source": [ "# Cleaning Terrain" ] }, { "cell_type": "code", "execution_count": 10, "id": "11a03b3e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Trail terrain (5 uniques): \n", " ['Light', 'Lightmoderate', 'Moderate', 'Moderatetechnical', 'Technical']\n" ] }, { "data": { "text/plain": [ "Trail terrain\n", "Lightmoderate 66\n", "Light 54\n", "Moderatetechnical 27\n", "Moderate 22\n", "Technical 12\n", "Name: count, dtype: int64" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Trail terrain\"] = (\n", " df[\"Trail terrain\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "terrain_uniques = df[\"Trail terrain\"].dropna().unique()\n", "# terrain_uniques.sort()\n", "terrain_uniques = sorted(terrain_uniques)\n", "print(f\"Trail terrain ({len(terrain_uniques)} uniques): \\n\",terrain_uniques)\n", "\n", "df[\"Trail terrain\"].value_counts().head(20)" ] }, { "cell_type": "code", "execution_count": 11, "id": "68ada20b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Forefoot lab Forefoot brandWidths availableFor heavy runnersSeasonRemovable insoleOrthotic friendlyWaterproofingRankingPopularityterrain_norm
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/forefoot...30.3 mm 30.0 mmNormal0All seasons11-#67 Top 19%#163 Top 45%Light
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelMid/forefoot...24.6 mm 18.0 mmNormal0-11-#45 Top 13%#294 Bottom 20%Light
2AltraExperience Wild88\\n Great!$145LightmoderateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/forefoot...30.2 mm 30.0 mmNormal0All seasons11-#251 Top 39%#308 Top 48%Light|Moderate
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/forefoot...26.2 mm 28.0 mmNormal0All seasons11-#315 Bottom 14%#211 Bottom 42%Light
4AltraLone Peak 5.091\\n Superb!$130LightmoderateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/forefoot...24.3 mm 25.0 mmNormal0-11-#62 Top 10%#63 Top 10%Light|Moderate
\n", "

5 rows × 34 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 Lightmoderate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 Lightmoderate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... Forefoot lab Forefoot brand Widths available \\\n", "0 Mid/forefoot ... 30.3 mm 30.0 mm Normal \n", "1 HeelMid/forefoot ... 24.6 mm 18.0 mm Normal \n", "2 Mid/forefoot ... 30.2 mm 30.0 mm Normal \n", "3 Mid/forefoot ... 26.2 mm 28.0 mm Normal \n", "4 Mid/forefoot ... 24.3 mm 25.0 mm Normal \n", "\n", " For heavy runners Season Removable insole Orthotic friendly \\\n", "0 0 All seasons 1 1 \n", "1 0 - 1 1 \n", "2 0 All seasons 1 1 \n", "3 0 All seasons 1 1 \n", "4 0 - 1 1 \n", "\n", " Waterproofing Ranking Popularity terrain_norm \n", "0 - #67 Top 19% #163 Top 45% Light \n", "1 - #45 Top 13% #294 Bottom 20% Light \n", "2 - #251 Top 39% #308 Top 48% Light|Moderate \n", "3 - #315 Bottom 14% #211 Bottom 42% Light \n", "4 - #62 Top 10% #63 Top 10% Light|Moderate \n", "\n", "[5 rows x 34 columns]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "terrain_map = {\n", " \"Light\": \"Light\",\n", " \"Moderate\": \"Moderate\",\n", " \"Technical\": \"Technical\",\n", " \"Lightmoderate\": \"Light|Moderate\",\n", " \"Moderatetechnical\": \"Moderate|Technical\",\n", "}\n", "\n", "df[\"terrain_norm\"] = df[\"Trail terrain\"].map(terrain_map)\n", "\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 12, "id": "dae161d5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UNMAPPED terrain values:\n", " Series([], Name: count, dtype: int64)\n" ] } ], "source": [ "unmapped = df[df[\"terrain_norm\"].isna()][\"Trail terrain\"].value_counts()\n", "print(\"UNMAPPED terrain values:\\n\", unmapped)\n", "# assert df[\"terrain_norm\"].notna().all()" ] }, { "cell_type": "code", "execution_count": 13, "id": "489fe0ed", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "terrain - norm : (5) uniques\n", " \n", "['Light', 'Light|Moderate', 'Moderate|Technical', 'Moderate', 'Technical']\n", "Length: 5, dtype: str\n" ] }, { "data": { "text/plain": [ "terrain_norm\n", "Light|Moderate 66\n", "Light 54\n", "Moderate|Technical 27\n", "Moderate 22\n", "Technical 12\n", "Name: count, dtype: int64" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "terrain_norms_unique = df[\"terrain_norm\"].dropna().unique()\n", "print(f\"terrain - norm : ({len(terrain_norms_unique)}) uniques\\n\", terrain_norms_unique)\n", "\n", "\n", "df[\"terrain_norm\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 14, "id": "8b96c34c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Widths availableFor heavy runnersSeasonRemovable insoleOrthotic friendlyWaterproofingRankingPopularityterrain_normterrain_lists
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/forefoot...Normal0All seasons11-#67 Top 19%#163 Top 45%Light[Light]
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelMid/forefoot...Normal0-11-#45 Top 13%#294 Bottom 20%Light[Light]
2AltraExperience Wild88\\n Great!$145LightmoderateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/forefoot...Normal0All seasons11-#251 Top 39%#308 Top 48%Light|Moderate[Light, Moderate]
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/forefoot...Normal0All seasons11-#315 Bottom 14%#211 Bottom 42%Light[Light]
4AltraLone Peak 5.091\\n Superb!$130LightmoderateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/forefoot...Normal0-11-#62 Top 10%#63 Top 10%Light|Moderate[Light, Moderate]
\n", "

5 rows × 35 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 Lightmoderate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 Lightmoderate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... Widths available For heavy runners Season \\\n", "0 Mid/forefoot ... Normal 0 All seasons \n", "1 HeelMid/forefoot ... Normal 0 - \n", "2 Mid/forefoot ... Normal 0 All seasons \n", "3 Mid/forefoot ... Normal 0 All seasons \n", "4 Mid/forefoot ... Normal 0 - \n", "\n", " Removable insole Orthotic friendly Waterproofing Ranking \\\n", "0 1 1 - #67 Top 19% \n", "1 1 1 - #45 Top 13% \n", "2 1 1 - #251 Top 39% \n", "3 1 1 - #315 Bottom 14% \n", "4 1 1 - #62 Top 10% \n", "\n", " Popularity terrain_norm terrain_lists \n", "0 #163 Top 45% Light [Light] \n", "1 #294 Bottom 20% Light [Light] \n", "2 #308 Top 48% Light|Moderate [Light, Moderate] \n", "3 #211 Bottom 42% Light [Light] \n", "4 #63 Top 10% Light|Moderate [Light, Moderate] \n", "\n", "[5 rows x 35 columns]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"terrain_lists\"] = df[\"terrain_norm\"].str.split(\"|\")\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 15, "id": "3a790715", "metadata": {}, "outputs": [], "source": [ "terrain_exploded = df[\"terrain_lists\"].explode()\n", "\n", "terrain_ohe = (\n", " pd.crosstab(terrain_exploded.index, terrain_exploded)\n", " .reindex(df.index, fill_value=0) \n", ")\n", "\n", "terrain_ohe = terrain_ohe.rename(columns={\n", " \"Light\": \"terrain_light\",\n", " \"Moderate\": \"terrain_moderate\",\n", " \"Technical\": \"terrain_technical\"\n", "})\n", "\n", "# gabung ke df\n", "df = pd.concat([df, terrain_ohe], axis=1)\n" ] }, { "cell_type": "code", "execution_count": 16, "id": "c51729b9", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Removable insoleOrthotic friendlyWaterproofingRankingPopularityterrain_normterrain_liststerrain_lightterrain_moderateterrain_technical
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/forefoot...11-#67 Top 19%#163 Top 45%Light[Light]100
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelMid/forefoot...11-#45 Top 13%#294 Bottom 20%Light[Light]100
2AltraExperience Wild88\\n Great!$145LightmoderateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/forefoot...11-#251 Top 39%#308 Top 48%Light|Moderate[Light, Moderate]110
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/forefoot...11-#315 Bottom 14%#211 Bottom 42%Light[Light]100
4AltraLone Peak 5.091\\n Superb!$130LightmoderateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/forefoot...11-#62 Top 10%#63 Top 10%Light|Moderate[Light, Moderate]110
\n", "

5 rows × 38 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 Lightmoderate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 Lightmoderate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... Removable insole Orthotic friendly Waterproofing \\\n", "0 Mid/forefoot ... 1 1 - \n", "1 HeelMid/forefoot ... 1 1 - \n", "2 Mid/forefoot ... 1 1 - \n", "3 Mid/forefoot ... 1 1 - \n", "4 Mid/forefoot ... 1 1 - \n", "\n", " Ranking Popularity terrain_norm terrain_lists \\\n", "0 #67 Top 19% #163 Top 45% Light [Light] \n", "1 #45 Top 13% #294 Bottom 20% Light [Light] \n", "2 #251 Top 39% #308 Top 48% Light|Moderate [Light, Moderate] \n", "3 #315 Bottom 14% #211 Bottom 42% Light [Light] \n", "4 #62 Top 10% #63 Top 10% Light|Moderate [Light, Moderate] \n", "\n", " terrain_light terrain_moderate terrain_technical \n", "0 1 0 0 \n", "1 1 0 0 \n", "2 1 1 0 \n", "3 1 0 0 \n", "4 1 1 0 \n", "\n", "[5 rows x 38 columns]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 17, "id": "d03312ce", "metadata": {}, "outputs": [], "source": [ "# make sure value-nya bener 0/1\n", "for c in [\"terrain_light\", \"terrain_moderate\", \"terrain_technical\"]:\n", " assert set(df[c].unique()).issubset({0, 1})" ] }, { "cell_type": "code", "execution_count": 18, "id": "62af3a33", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Trail terrain terrain_norm terrain_light terrain_moderate \\\n", "0 Light Light 1 0 \n", "1 Light Light 1 0 \n", "3 Light Light 1 0 \n", "13 Light Light 1 0 \n", "14 Light Light 1 0 \n", "\n", " terrain_technical \n", "0 0 \n", "1 0 \n", "3 0 \n", "13 0 \n", "14 0 \n", " Trail terrain terrain_norm terrain_moderate terrain_technical \\\n", "6 Moderate Moderate 1 0 \n", "10 Moderate Moderate 1 0 \n", "48 Moderate Moderate 1 0 \n", "49 Moderate Moderate 1 0 \n", "50 Moderate Moderate 1 0 \n", "\n", " terrain_light \n", "6 0 \n", "10 0 \n", "48 0 \n", "49 0 \n", "50 0 \n" ] } ], "source": [ "print(df[df[\"Trail terrain\"]==\"Light\"][[\"Trail terrain\",\"terrain_norm\",\"terrain_light\",\"terrain_moderate\",\"terrain_technical\"]].head())\n", "print(df[df[\"Trail terrain\"]==\"Moderate\"][[\"Trail terrain\",\"terrain_norm\",\"terrain_moderate\",\"terrain_technical\",\"terrain_light\"]].head())" ] }, { "cell_type": "code", "execution_count": 19, "id": "6eccf7c1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 183\n", "light sum: 120\n", "moderate sum: 115\n", "technical sum: 39\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"light sum:\", int(df[\"terrain_light\"].sum()))\n", "print(\"moderate sum:\", int(df[\"terrain_moderate\"].sum()))\n", "print(\"technical sum:\", int(df[\"terrain_technical\"].sum()))" ] }, { "cell_type": "markdown", "id": "d1730fa8", "metadata": {}, "source": [ "# Cleaning arch support" ] }, { "cell_type": "code", "execution_count": 21, "id": "48fb916e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Arch (2 uniques): \n", " ['Neutral', 'Stability']\n" ] }, { "data": { "text/plain": [ "Arch support\n", "Neutral 177\n", "Stability 4\n", "Name: count, dtype: int64" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Arch support\"] = (\n", " df[\"Arch support\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "arch_uniques = df[\"Arch support\"].dropna().unique()\n", "# arch_uniques.sort()\n", "arch_uniques = sorted(arch_uniques)\n", "print(f\"Arch ({len(arch_uniques)} uniques): \\n\",arch_uniques)\n", "\n", "df[\"Arch support\"].value_counts().head(20)" ] }, { "cell_type": "code", "execution_count": 22, "id": "fdc2e1c5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Arch_grouped\n", "Neutral 177\n", "Stability 4\n", "Name: count, dtype: int64\n" ] } ], "source": [ "arch_map = {\n", " \"Neutral\": \"Neutral\",\n", " \"Stability\": \"Stability\",\n", "}\n", "\n", "df[\"Arch_grouped\"] = df[\"Arch support\"].map(arch_map)\n", "\n", "print(df[\"Arch_grouped\"].value_counts())" ] }, { "cell_type": "code", "execution_count": 23, "id": "2e5b55df", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...RankingPopularityterrain_normterrain_liststerrain_lightterrain_moderateterrain_technicalArch_groupedarch_neutralarch_stability
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/forefoot...#67 Top 19%#163 Top 45%Light[Light]100Neutral10
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelMid/forefoot...#45 Top 13%#294 Bottom 20%Light[Light]100Neutral10
2AltraExperience Wild88\\n Great!$145LightmoderateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/forefoot...#251 Top 39%#308 Top 48%Light|Moderate[Light, Moderate]110Neutral10
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/forefoot...#315 Bottom 14%#211 Bottom 42%Light[Light]100Neutral10
4AltraLone Peak 5.091\\n Superb!$130LightmoderateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/forefoot...#62 Top 10%#63 Top 10%Light|Moderate[Light, Moderate]110Neutral10
\n", "

5 rows × 41 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 Lightmoderate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 Lightmoderate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... Ranking Popularity terrain_norm \\\n", "0 Mid/forefoot ... #67 Top 19% #163 Top 45% Light \n", "1 HeelMid/forefoot ... #45 Top 13% #294 Bottom 20% Light \n", "2 Mid/forefoot ... #251 Top 39% #308 Top 48% Light|Moderate \n", "3 Mid/forefoot ... #315 Bottom 14% #211 Bottom 42% Light \n", "4 Mid/forefoot ... #62 Top 10% #63 Top 10% Light|Moderate \n", "\n", " terrain_lists terrain_light terrain_moderate terrain_technical \\\n", "0 [Light] 1 0 0 \n", "1 [Light] 1 0 0 \n", "2 [Light, Moderate] 1 1 0 \n", "3 [Light] 1 0 0 \n", "4 [Light, Moderate] 1 1 0 \n", "\n", " Arch_grouped arch_neutral arch_stability \n", "0 Neutral 1 0 \n", "1 Neutral 1 0 \n", "2 Neutral 1 0 \n", "3 Neutral 1 0 \n", "4 Neutral 1 0 \n", "\n", "[5 rows x 41 columns]" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "arch_ohe = pd.get_dummies(df[\"Arch_grouped\"], prefix=\"arch\", dtype=int)\n", "\n", "arch_ohe = arch_ohe.rename(columns={\n", " \"arch_Neutral\": \"arch_neutral\",\n", " \"arch_Stability\": \"arch_stability\"\n", "})\n", "\n", "df = pd.concat([df, arch_ohe], axis=1)\n", "df.head()\n" ] }, { "cell_type": "code", "execution_count": 24, "id": "2998a49f", "metadata": {}, "outputs": [], "source": [ "# jujur arch grouped gaperlu jadi kita buang aja\n", "# df = df.drop(labels=\"Arch_grouped\", axis=1)" ] }, { "cell_type": "code", "execution_count": 25, "id": "715b4a89", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Validasi One-Hot Encoding Arch Support:\n", " Arch support arch_neutral arch_stability\n", "0 Neutral 1 0\n", "1 Neutral 1 0\n", "2 Neutral 1 0\n", "3 Neutral 1 0\n", "4 Neutral 1 0\n", "5 Neutral 1 0\n", "6 Neutral 1 0\n", "7 Neutral 1 0\n", "8 Neutral 1 0\n", "9 Neutral 1 0\n", "\n", "Total Neutral : 177\n", "Total Stability : 4\n" ] } ], "source": [ "# assert (df[\"arch_neutral\"] + df[\"arch_stability\"] == 1).all(), \"Error: Ada baris yang tidak punya kategori arch atau ganda!\"\n", "\n", "print(\"\\nValidasi One-Hot Encoding Arch Support:\")\n", "print(df[[\"Arch support\", \"arch_neutral\", \"arch_stability\"]].head(10))\n", "\n", "# Cek total count untuk laporan\n", "print(\"\\nTotal Neutral :\", df[\"arch_neutral\"].sum())\n", "print(\"Total Stability :\", df[\"arch_stability\"].sum())" ] }, { "cell_type": "markdown", "id": "5344af8e", "metadata": {}, "source": [ "# Cleaning Strike" ] }, { "cell_type": "code", "execution_count": 27, "id": "45d6d7b0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Strike pattern (3 uniques): \n", " ['Heel', 'Heelmid/Forefoot', 'Mid/Forefoot']\n" ] }, { "data": { "text/plain": [ "Strike pattern\n", "Mid/Forefoot 96\n", "Heel 50\n", "Heelmid/Forefoot 35\n", "Name: count, dtype: int64" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Strike pattern\"] = (\n", " df[\"Strike pattern\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "strike_pattern_uniques = df[\"Strike pattern\"].dropna().unique()\n", "# strike_pattern_uniques.sort()\n", "strike_pattern_uniques = sorted(strike_pattern_uniques)\n", "print(f\"Strike pattern ({len(strike_pattern_uniques)} uniques): \\n\",strike_pattern_uniques)\n", "\n", "df[\"Strike pattern\"].value_counts().head(20)" ] }, { "cell_type": "code", "execution_count": 28, "id": "5bcb981a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UNMAPPED strike values:\n", " Series([], Name: count, dtype: int64)\n" ] } ], "source": [ "# ['-' 'Heel' 'Heel Mid/Forefoot' 'Heelmid/Forefoot' 'Mid/Forefoot']\n", "\n", "\n", "strike_map = {\n", " \"Mid/Forefoot\": \"Mid|Forefoot\",\n", " \"Heelmid/Forefoot\": \"Heel|Mid|Forefoot\",\n", " \"Heel\": \"Heel\",\n", "}\n", "\n", "df[\"Strike_norm\"] = df[\"Strike pattern\"].map(strike_map)\n", "\n", "unmapped = df[df[\"Strike_norm\"].isna()][\"Strike pattern\"].value_counts()\n", "print(\"UNMAPPED strike values:\\n\", unmapped)\n", "# assert df[\"Strike_norm\"].notna().all()" ] }, { "cell_type": "code", "execution_count": 29, "id": "c30b882d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Strike - norm : (3) uniques\n", " \n", "['Mid|Forefoot', 'Heel|Mid|Forefoot', 'Heel']\n", "Length: 3, dtype: str\n" ] }, { "data": { "text/plain": [ "Strike_norm\n", "Mid|Forefoot 96\n", "Heel 50\n", "Heel|Mid|Forefoot 35\n", "Name: count, dtype: int64" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "strike_norm_unique = df[\"Strike_norm\"].dropna().unique()\n", "print(f\"Strike - norm : ({len(strike_norm_unique)}) uniques\\n\", strike_norm_unique)\n", "\n", "\n", "df[\"Strike_norm\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 30, "id": "ecaca627", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...terrain_normterrain_liststerrain_lightterrain_moderateterrain_technicalArch_groupedarch_neutralarch_stabilityStrike_normStrike_lists
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral9.1 oz / 259g 9.5 oz / 270g00.3 mm 8.0 mmMid/Forefoot...Light[Light]100Neutral10Mid|Forefoot[Mid, Forefoot]
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral9.1 oz / 258g 9 oz / 255g08.2 mm 8.0 mmHeelmid/Forefoot...Light[Light]100Neutral10Heel|Mid|Forefoot[Heel, Mid, Forefoot]
2AltraExperience Wild88\\n Great!$145LightmoderateNeutral10.1 oz / 285g 9.6 oz / 273g04.3 mm 4.0 mmMid/Forefoot...Light|Moderate[Light, Moderate]110Neutral10Mid|Forefoot[Mid, Forefoot]
3AltraExperience Wild 279\\n Good!$140LightNeutral9.4 oz / 266g 10.3 oz / 293g06.1 mm 4.0 mmMid/Forefoot...Light[Light]100Neutral10Mid|Forefoot[Mid, Forefoot]
4AltraLone Peak 5.091\\n Superb!$130LightmoderateNeutral10.7 oz / 302g 10.6 oz / 301g00.2 mm 0.0 mmMid/Forefoot...Light|Moderate[Light, Moderate]110Neutral10Mid|Forefoot[Mid, Forefoot]
\n", "

5 rows × 43 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 Lightmoderate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 Lightmoderate \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 Neutral 9.1 oz / 259g 9.5 oz / 270g 0 0.3 mm 8.0 mm \n", "1 Neutral 9.1 oz / 258g 9 oz / 255g 0 8.2 mm 8.0 mm \n", "2 Neutral 10.1 oz / 285g 9.6 oz / 273g 0 4.3 mm 4.0 mm \n", "3 Neutral 9.4 oz / 266g 10.3 oz / 293g 0 6.1 mm 4.0 mm \n", "4 Neutral 10.7 oz / 302g 10.6 oz / 301g 0 0.2 mm 0.0 mm \n", "\n", " Strike pattern ... terrain_norm terrain_lists terrain_light \\\n", "0 Mid/Forefoot ... Light [Light] 1 \n", "1 Heelmid/Forefoot ... Light [Light] 1 \n", "2 Mid/Forefoot ... Light|Moderate [Light, Moderate] 1 \n", "3 Mid/Forefoot ... Light [Light] 1 \n", "4 Mid/Forefoot ... Light|Moderate [Light, Moderate] 1 \n", "\n", " terrain_moderate terrain_technical Arch_grouped arch_neutral arch_stability \\\n", "0 0 0 Neutral 1 0 \n", "1 0 0 Neutral 1 0 \n", "2 1 0 Neutral 1 0 \n", "3 0 0 Neutral 1 0 \n", "4 1 0 Neutral 1 0 \n", "\n", " Strike_norm Strike_lists \n", "0 Mid|Forefoot [Mid, Forefoot] \n", "1 Heel|Mid|Forefoot [Heel, Mid, Forefoot] \n", "2 Mid|Forefoot [Mid, Forefoot] \n", "3 Mid|Forefoot [Mid, Forefoot] \n", "4 Mid|Forefoot [Mid, Forefoot] \n", "\n", "[5 rows x 43 columns]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Strike_lists\"] = df[\"Strike_norm\"].str.split(\"|\")\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 31, "id": "10b41050", "metadata": {}, "outputs": [], "source": [ "strike_exploded = df[\"Strike_lists\"].explode()\n", "\n", "strike_ohe = (\n", " pd.crosstab(strike_exploded.index, strike_exploded)\n", " .reindex(df.index, fill_value=0) # jaga urutan index sama df\n", ")\n", "\n", "strike_ohe = strike_ohe.rename(columns={\n", " \"Heel\": \"strike_heel\",\n", " \"Mid\": \"strike_mid\",\n", " \"Forefoot\": \"strike_forefoot\"\n", "})\n", "\n", "df = pd.concat([df, strike_ohe], axis=1)\n" ] }, { "cell_type": "code", "execution_count": 32, "id": "c1164248", "metadata": {}, "outputs": [], "source": [ "for c in [\"strike_heel\", \"strike_mid\", \"strike_forefoot\"]:\n", " assert set(df[c].unique()).issubset({0, 1})" ] }, { "cell_type": "code", "execution_count": 33, "id": "8af9e800", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 183\n", "Heels sum: 85\n", "Mid sum: 131\n", "Forefoot sum: 131\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"Heels sum:\", int(df[\"strike_heel\"].sum()))\n", "print(\"Mid sum:\", int(df[\"strike_mid\"].sum()))\n", "print(\"Forefoot sum:\", int(df[\"strike_forefoot\"].sum()))" ] }, { "cell_type": "code", "execution_count": 34, "id": "ab00d7b5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 46 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Trail terrain 181 non-null str \n", " 5 Arch support 181 non-null str \n", " 6 Weight lab Weight brand 181 non-null str \n", " 7 Lightweight 181 non-null str \n", " 8 Drop lab Drop brand 181 non-null str \n", " 9 Strike pattern 181 non-null str \n", " 10 Size 181 non-null str \n", " 11 Midsole softness 181 non-null str \n", " 12 Plate 180 non-null str \n", " 13 Toebox durability 181 non-null str \n", " 14 Heel padding durability 181 non-null str \n", " 15 Outsole durability 181 non-null str \n", " 16 Breathability 181 non-null str \n", " 17 Width / fit 181 non-null str \n", " 18 Toebox width 181 non-null str \n", " 19 Stiffness 181 non-null str \n", " 20 Torsional rigidity 181 non-null str \n", " 21 Heel counter stiffness 181 non-null str \n", " 22 Lug depth 181 non-null str \n", " 23 Heel stack lab Heel stack brand 181 non-null str \n", " 24 Forefoot lab Forefoot brand 181 non-null str \n", " 25 Widths available 181 non-null str \n", " 26 For heavy runners 181 non-null str \n", " 27 Season 181 non-null str \n", " 28 Removable insole 181 non-null str \n", " 29 Orthotic friendly 181 non-null str \n", " 30 Waterproofing 180 non-null str \n", " 31 Ranking 181 non-null str \n", " 32 Popularity 181 non-null str \n", " 33 terrain_norm 181 non-null str \n", " 34 terrain_lists 181 non-null object\n", " 35 terrain_light 183 non-null int64 \n", " 36 terrain_moderate 183 non-null int64 \n", " 37 terrain_technical 183 non-null int64 \n", " 38 Arch_grouped 181 non-null str \n", " 39 arch_neutral 183 non-null int64 \n", " 40 arch_stability 183 non-null int64 \n", " 41 Strike_norm 181 non-null str \n", " 42 Strike_lists 181 non-null object\n", " 43 strike_forefoot 183 non-null int64 \n", " 44 strike_heel 183 non-null int64 \n", " 45 strike_mid 183 non-null int64 \n", "dtypes: int64(8), object(2), str(36)\n", "memory usage: 65.9+ KB\n", "None\n" ] } ], "source": [ "df.head()\n", "print(df.info())" ] }, { "cell_type": "code", "execution_count": 35, "id": "eeb2d2c7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Neutral', 'Stability', nan]\n", "Length: 3, dtype: str\n" ] } ], "source": [ "print(df[\"Arch_grouped\"].unique())" ] }, { "cell_type": "markdown", "id": "b9f6608a", "metadata": {}, "source": [ "# Split Wight Lab Weight Brand" ] }, { "cell_type": "code", "execution_count": 36, "id": "f1989222", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(2)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask_missing = (\n", " df[\"Weight lab Weight brand\"].isna() |\n", " (df[\"Weight lab Weight brand\"].astype(str).str.strip() == \"-\")\n", ")\n", "mask_missing.sum()" ] }, { "cell_type": "code", "execution_count": 37, "id": "7b357341", "metadata": {}, "outputs": [], "source": [ "# weight = df[\"Weight lab Weight brand\"].fillna(\"\").str.findall(r\"[\\d.]+\")\n", "\n", "# # Fill missing values with empty lists\n", "# weight = weight.apply(lambda x: x if isinstance(x, list) else [])\n", "\n", "# # Expand the lists into separate columns\n", "# weight_df = pd.DataFrame(weight.tolist(), index=df.index)\n", "\n", "# # Handle cases where we have fewer than 4 columns\n", "# while len(weight_df.columns) < 4:\n", "# weight_df[len(weight_df.columns)] = None\n", "\n", "# df[[\"weight_lab_oz\", \"weight_lab_g\", \"weight_brand_oz\", \"weight_brand_g\"]] = weight_df.iloc[:, :4]\n", "\n", "# for col in [\"weight_lab_oz\", \"weight_lab_g\", \"weight_brand_oz\", \"weight_brand_g\"]:\n", "# df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "# print(df[[\"weight_lab_oz\", \"weight_lab_g\", \"weight_brand_oz\", \"weight_brand_g\"]].head())" ] }, { "cell_type": "code", "execution_count": 38, "id": "a3ba22a7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 46 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Trail terrain 181 non-null str \n", " 5 Arch support 181 non-null str \n", " 6 Weight lab Weight brand 181 non-null str \n", " 7 Lightweight 181 non-null str \n", " 8 Drop lab Drop brand 181 non-null str \n", " 9 Strike pattern 181 non-null str \n", " 10 Size 181 non-null str \n", " 11 Midsole softness 181 non-null str \n", " 12 Plate 180 non-null str \n", " 13 Toebox durability 181 non-null str \n", " 14 Heel padding durability 181 non-null str \n", " 15 Outsole durability 181 non-null str \n", " 16 Breathability 181 non-null str \n", " 17 Width / fit 181 non-null str \n", " 18 Toebox width 181 non-null str \n", " 19 Stiffness 181 non-null str \n", " 20 Torsional rigidity 181 non-null str \n", " 21 Heel counter stiffness 181 non-null str \n", " 22 Lug depth 181 non-null str \n", " 23 Heel stack lab Heel stack brand 181 non-null str \n", " 24 Forefoot lab Forefoot brand 181 non-null str \n", " 25 Widths available 181 non-null str \n", " 26 For heavy runners 181 non-null str \n", " 27 Season 181 non-null str \n", " 28 Removable insole 181 non-null str \n", " 29 Orthotic friendly 181 non-null str \n", " 30 Waterproofing 180 non-null str \n", " 31 Ranking 181 non-null str \n", " 32 Popularity 181 non-null str \n", " 33 terrain_norm 181 non-null str \n", " 34 terrain_lists 181 non-null object\n", " 35 terrain_light 183 non-null int64 \n", " 36 terrain_moderate 183 non-null int64 \n", " 37 terrain_technical 183 non-null int64 \n", " 38 Arch_grouped 181 non-null str \n", " 39 arch_neutral 183 non-null int64 \n", " 40 arch_stability 183 non-null int64 \n", " 41 Strike_norm 181 non-null str \n", " 42 Strike_lists 181 non-null object\n", " 43 strike_forefoot 183 non-null int64 \n", " 44 strike_heel 183 non-null int64 \n", " 45 strike_mid 183 non-null int64 \n", "dtypes: int64(8), object(2), str(36)\n", "memory usage: 65.9+ KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 39, "id": "3ef08676", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceTrail terrainArch supportLightweightDrop lab Drop brandStrike patternSize...terrain_lightterrain_moderateterrain_technicalArch_groupedarch_neutralarch_stabilityStrike_normstrike_forefootstrike_heelstrike_mid
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$220LightNeutral00.3 mm 8.0 mmMid/ForefootSlightly large...100Neutral10Mid|Forefoot101
1AdidasTerrex Speed Ultra90\\n Superb!$160LightNeutral08.2 mm 8.0 mmHeelmid/ForefootTrue to size...100Neutral10Heel|Mid|Forefoot111
2AltraExperience Wild88\\n Great!$145LightmoderateNeutral04.3 mm 4.0 mmMid/ForefootTrue to size...110Neutral10Mid|Forefoot101
3AltraExperience Wild 279\\n Good!$140LightNeutral06.1 mm 4.0 mmMid/Forefoot-...100Neutral10Mid|Forefoot101
4AltraLone Peak 5.091\\n Superb!$130LightmoderateNeutral00.2 mm 0.0 mmMid/ForefootTrue to size...110Neutral10Mid|Forefoot101
\n", "

5 rows × 43 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Trail terrain \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 Light \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 Light \n", "2 Altra Experience Wild 88\\n Great! $145 Lightmoderate \n", "3 Altra Experience Wild 2 79\\n Good! $140 Light \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 Lightmoderate \n", "\n", " Arch support Lightweight Drop lab Drop brand Strike pattern \\\n", "0 Neutral 0 0.3 mm 8.0 mm Mid/Forefoot \n", "1 Neutral 0 8.2 mm 8.0 mm Heelmid/Forefoot \n", "2 Neutral 0 4.3 mm 4.0 mm Mid/Forefoot \n", "3 Neutral 0 6.1 mm 4.0 mm Mid/Forefoot \n", "4 Neutral 0 0.2 mm 0.0 mm Mid/Forefoot \n", "\n", " Size ... terrain_light terrain_moderate terrain_technical \\\n", "0 Slightly large ... 1 0 0 \n", "1 True to size ... 1 0 0 \n", "2 True to size ... 1 1 0 \n", "3 - ... 1 0 0 \n", "4 True to size ... 1 1 0 \n", "\n", " Arch_grouped arch_neutral arch_stability Strike_norm strike_forefoot \\\n", "0 Neutral 1 0 Mid|Forefoot 1 \n", "1 Neutral 1 0 Heel|Mid|Forefoot 1 \n", "2 Neutral 1 0 Mid|Forefoot 1 \n", "3 Neutral 1 0 Mid|Forefoot 1 \n", "4 Neutral 1 0 Mid|Forefoot 1 \n", "\n", " strike_heel strike_mid \n", "0 0 1 \n", "1 1 1 \n", "2 0 1 \n", "3 0 1 \n", "4 0 1 \n", "\n", "[5 rows x 43 columns]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.drop(columns=[\"Weight lab Weight brand\",\"terrain_lists\",\"Strike_lists\"], inplace=True)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 40, "id": "ca5feca3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 43 columns):\n", " # Column Non-Null Count Dtype\n", "--- ------ -------------- -----\n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Trail terrain 181 non-null str \n", " 5 Arch support 181 non-null str \n", " 6 Lightweight 181 non-null str \n", " 7 Drop lab Drop brand 181 non-null str \n", " 8 Strike pattern 181 non-null str \n", " 9 Size 181 non-null str \n", " 10 Midsole softness 181 non-null str \n", " 11 Plate 180 non-null str \n", " 12 Toebox durability 181 non-null str \n", " 13 Heel padding durability 181 non-null str \n", " 14 Outsole durability 181 non-null str \n", " 15 Breathability 181 non-null str \n", " 16 Width / fit 181 non-null str \n", " 17 Toebox width 181 non-null str \n", " 18 Stiffness 181 non-null str \n", " 19 Torsional rigidity 181 non-null str \n", " 20 Heel counter stiffness 181 non-null str \n", " 21 Lug depth 181 non-null str \n", " 22 Heel stack lab Heel stack brand 181 non-null str \n", " 23 Forefoot lab Forefoot brand 181 non-null str \n", " 24 Widths available 181 non-null str \n", " 25 For heavy runners 181 non-null str \n", " 26 Season 181 non-null str \n", " 27 Removable insole 181 non-null str \n", " 28 Orthotic friendly 181 non-null str \n", " 29 Waterproofing 180 non-null str \n", " 30 Ranking 181 non-null str \n", " 31 Popularity 181 non-null str \n", " 32 terrain_norm 181 non-null str \n", " 33 terrain_light 183 non-null int64\n", " 34 terrain_moderate 183 non-null int64\n", " 35 terrain_technical 183 non-null int64\n", " 36 Arch_grouped 181 non-null str \n", " 37 arch_neutral 183 non-null int64\n", " 38 arch_stability 183 non-null int64\n", " 39 Strike_norm 181 non-null str \n", " 40 strike_forefoot 183 non-null int64\n", " 41 strike_heel 183 non-null int64\n", " 42 strike_mid 183 non-null int64\n", "dtypes: int64(8), str(35)\n", "memory usage: 61.6 KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 41, "id": "8316aaa1", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightDrop lab Drop brandStrike patternSizeMidsole softnessPlate...terrain_lightterrain_moderateterrain_technicalArch_groupedarch_neutralarch_stabilityStrike_normstrike_forefootstrike_heelstrike_mid
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$22000.3 mm 8.0 mmMid/ForefootSlightly largeBalanced0...100Neutral10Mid|Forefoot101
1AdidasTerrex Speed Ultra90\\n Superb!$16008.2 mm 8.0 mmHeelmid/ForefootTrue to size-0...100Neutral10Heel|Mid|Forefoot111
2AltraExperience Wild88\\n Great!$14504.3 mm 4.0 mmMid/ForefootTrue to sizeSoft0...110Neutral10Mid|Forefoot101
3AltraExperience Wild 279\\n Good!$14006.1 mm 4.0 mmMid/Forefoot-Balanced0...100Neutral10Mid|Forefoot101
4AltraLone Peak 5.091\\n Superb!$13000.2 mm 0.0 mmMid/ForefootTrue to size-Rock plate...110Neutral10Mid|Forefoot101
\n", "

5 rows × 41 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Drop lab Drop brand Strike pattern Size Midsole softness \\\n", "0 0.3 mm 8.0 mm Mid/Forefoot Slightly large Balanced \n", "1 8.2 mm 8.0 mm Heelmid/Forefoot True to size - \n", "2 4.3 mm 4.0 mm Mid/Forefoot True to size Soft \n", "3 6.1 mm 4.0 mm Mid/Forefoot - Balanced \n", "4 0.2 mm 0.0 mm Mid/Forefoot True to size - \n", "\n", " Plate ... terrain_light terrain_moderate terrain_technical \\\n", "0 0 ... 1 0 0 \n", "1 0 ... 1 0 0 \n", "2 0 ... 1 1 0 \n", "3 0 ... 1 0 0 \n", "4 Rock plate ... 1 1 0 \n", "\n", " Arch_grouped arch_neutral arch_stability Strike_norm strike_forefoot \\\n", "0 Neutral 1 0 Mid|Forefoot 1 \n", "1 Neutral 1 0 Heel|Mid|Forefoot 1 \n", "2 Neutral 1 0 Mid|Forefoot 1 \n", "3 Neutral 1 0 Mid|Forefoot 1 \n", "4 Neutral 1 0 Mid|Forefoot 1 \n", "\n", " strike_heel strike_mid \n", "0 0 1 \n", "1 1 1 \n", "2 0 1 \n", "3 0 1 \n", "4 0 1 \n", "\n", "[5 rows x 41 columns]" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.drop(columns=[\"Trail terrain\", \"Arch support\"], inplace=True)\n", "df.head()" ] }, { "cell_type": "markdown", "id": "32c33365", "metadata": {}, "source": [ "# Split Drop Lab Drop Brand" ] }, { "cell_type": "code", "execution_count": 42, "id": "32a1491d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(2)" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask_missing = (\n", " df[\"Drop lab Drop brand\"].isna() |\n", " (df[\"Drop lab Drop brand\"].astype(str).str.strip() == \"-\")\n", ")\n", "mask_missing.sum()\n", "\n" ] }, { "cell_type": "code", "execution_count": 43, "id": "f8d8e3bf", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Drop lab Drop brand drop_lab_mm drop_brand_mm\n", "0 0.3 mm 8.0 mm 0.3 8.0\n", "1 8.2 mm 8.0 mm 8.2 8.0\n", "2 4.3 mm 4.0 mm 4.3 4.0\n", "3 6.1 mm 4.0 mm 6.1 4.0\n", "4 0.2 mm 0.0 mm 0.2 0.0\n" ] } ], "source": [ "drop = df[\"Drop lab Drop brand\"].fillna(\"\").str.findall(r\"[\\d.]+\")\n", "\n", "# Fill missing values with empty lists\n", "drop = drop.apply(lambda x: x if isinstance(x, list) else [])\n", "\n", "# Expand the lists into separate columns\n", "drop_df = pd.DataFrame(drop.tolist(), index=df.index)\n", "\n", "# Handle cases where we have fewer than 2 columns\n", "while len(drop_df.columns) < 2:\n", " drop_df[len(drop_df.columns)] = None\n", "\n", "df[[\"drop_lab_mm\", \"drop_brand_mm\"]] = drop_df.iloc[:, :2]\n", "\n", "for col in [\"drop_lab_mm\", \"drop_brand_mm\"]:\n", " df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "print(df[[\"Drop lab Drop brand\", \"drop_lab_mm\", \"drop_brand_mm\"]].head())" ] }, { "cell_type": "code", "execution_count": 44, "id": "e29836d6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 42 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Strike pattern 181 non-null str \n", " 6 Size 181 non-null str \n", " 7 Midsole softness 181 non-null str \n", " 8 Plate 180 non-null str \n", " 9 Toebox durability 181 non-null str \n", " 10 Heel padding durability 181 non-null str \n", " 11 Outsole durability 181 non-null str \n", " 12 Breathability 181 non-null str \n", " 13 Width / fit 181 non-null str \n", " 14 Toebox width 181 non-null str \n", " 15 Stiffness 181 non-null str \n", " 16 Torsional rigidity 181 non-null str \n", " 17 Heel counter stiffness 181 non-null str \n", " 18 Lug depth 181 non-null str \n", " 19 Heel stack lab Heel stack brand 181 non-null str \n", " 20 Forefoot lab Forefoot brand 181 non-null str \n", " 21 Widths available 181 non-null str \n", " 22 For heavy runners 181 non-null str \n", " 23 Season 181 non-null str \n", " 24 Removable insole 181 non-null str \n", " 25 Orthotic friendly 181 non-null str \n", " 26 Waterproofing 180 non-null str \n", " 27 Ranking 181 non-null str \n", " 28 Popularity 181 non-null str \n", " 29 terrain_norm 181 non-null str \n", " 30 terrain_light 183 non-null int64 \n", " 31 terrain_moderate 183 non-null int64 \n", " 32 terrain_technical 183 non-null int64 \n", " 33 Arch_grouped 181 non-null str \n", " 34 arch_neutral 183 non-null int64 \n", " 35 arch_stability 183 non-null int64 \n", " 36 Strike_norm 181 non-null str \n", " 37 strike_forefoot 183 non-null int64 \n", " 38 strike_heel 183 non-null int64 \n", " 39 strike_mid 183 non-null int64 \n", " 40 drop_lab_mm 181 non-null float64\n", " 41 drop_brand_mm 174 non-null float64\n", "dtypes: float64(2), int64(8), str(32)\n", "memory usage: 60.2 KB\n" ] } ], "source": [ "df.drop(columns=[\"Drop lab Drop brand\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "code", "execution_count": 45, "id": "1fe64880", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 41 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Midsole softness 181 non-null str \n", " 7 Plate 180 non-null str \n", " 8 Toebox durability 181 non-null str \n", " 9 Heel padding durability 181 non-null str \n", " 10 Outsole durability 181 non-null str \n", " 11 Breathability 181 non-null str \n", " 12 Width / fit 181 non-null str \n", " 13 Toebox width 181 non-null str \n", " 14 Stiffness 181 non-null str \n", " 15 Torsional rigidity 181 non-null str \n", " 16 Heel counter stiffness 181 non-null str \n", " 17 Lug depth 181 non-null str \n", " 18 Heel stack lab Heel stack brand 181 non-null str \n", " 19 Forefoot lab Forefoot brand 181 non-null str \n", " 20 Widths available 181 non-null str \n", " 21 For heavy runners 181 non-null str \n", " 22 Season 181 non-null str \n", " 23 Removable insole 181 non-null str \n", " 24 Orthotic friendly 181 non-null str \n", " 25 Waterproofing 180 non-null str \n", " 26 Ranking 181 non-null str \n", " 27 Popularity 181 non-null str \n", " 28 terrain_norm 181 non-null str \n", " 29 terrain_light 183 non-null int64 \n", " 30 terrain_moderate 183 non-null int64 \n", " 31 terrain_technical 183 non-null int64 \n", " 32 Arch_grouped 181 non-null str \n", " 33 arch_neutral 183 non-null int64 \n", " 34 arch_stability 183 non-null int64 \n", " 35 Strike_norm 181 non-null str \n", " 36 strike_forefoot 183 non-null int64 \n", " 37 strike_heel 183 non-null int64 \n", " 38 strike_mid 183 non-null int64 \n", " 39 drop_lab_mm 181 non-null float64\n", " 40 drop_brand_mm 174 non-null float64\n", "dtypes: float64(2), int64(8), str(31)\n", "memory usage: 58.7 KB\n" ] } ], "source": [ "df.drop(columns=[\"Strike pattern\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "6125a966", "metadata": {}, "source": [ "# Cleaning Midsole Softness" ] }, { "cell_type": "code", "execution_count": 47, "id": "607f2da7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Midsole (4 uniques): \n", " ['-', 'Balanced', 'Firm', 'Soft']\n" ] }, { "data": { "text/plain": [ "Midsole softness\n", "Balanced 74\n", "Soft 68\n", "- 24\n", "Firm 15\n", "Name: count, dtype: int64" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Midsole softness\"] = (\n", " df[\"Midsole softness\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "midsole_uniques = df[\"Midsole softness\"].dropna().unique()\n", "# midsole_uniques.sort()\n", "midsole_uniques = sorted(midsole_uniques)\n", "print(f\"Midsole ({len(midsole_uniques)} uniques): \\n\",midsole_uniques)\n", "\n", "df[\"Midsole softness\"].value_counts().head(20)" ] }, { "cell_type": "code", "execution_count": 48, "id": "d7c4cbc4", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameMidsole softnessmidsole_repr
1AdidasTerrex Speed Ultra-'-'
4AltraLone Peak 5.0-'-'
5AltraLone Peak 6-'-'
9AltraMont Blanc-'-'
29BrooksCascadia 16-'-'
57HokaZinal-'-'
70MerrellNova 2-'-'
78New BalanceFresh Foam Hierro v6-'-'
87New BalanceShando-'-'
89NikeAir Zoom Terra Kiger 6-'-'
90NikeJuniper Trail-'-'
96NikePegasus Trail 3 GTX-'-'
105NikeWildhorse 7-'-'
122SalomonSense Pro 4-'-'
123SalomonSense Ride 4-'-'
142SauconyEndorphin Trail-'-'
143SauconyPeregrine 11-'-'
144SauconyPeregrine 12-'-'
170KailasFuga EX BOA-'-'
174KailasFuga Pro 4-'-'
175KailasFuga EX 2-'-'
176KailasFuga Elite 2-'-'
178KailasFlythorn Air 2.0-'-'
180NikePegasus Trail 4-'-'
\n", "
" ], "text/plain": [ " Brand Name Midsole softness midsole_repr\n", "1 Adidas Terrex Speed Ultra - '-'\n", "4 Altra Lone Peak 5.0 - '-'\n", "5 Altra Lone Peak 6 - '-'\n", "9 Altra Mont Blanc - '-'\n", "29 Brooks Cascadia 16 - '-'\n", "57 Hoka Zinal - '-'\n", "70 Merrell Nova 2 - '-'\n", "78 New Balance Fresh Foam Hierro v6 - '-'\n", "87 New Balance Shando - '-'\n", "89 Nike Air Zoom Terra Kiger 6 - '-'\n", "90 Nike Juniper Trail - '-'\n", "96 Nike Pegasus Trail 3 GTX - '-'\n", "105 Nike Wildhorse 7 - '-'\n", "122 Salomon Sense Pro 4 - '-'\n", "123 Salomon Sense Ride 4 - '-'\n", "142 Saucony Endorphin Trail - '-'\n", "143 Saucony Peregrine 11 - '-'\n", "144 Saucony Peregrine 12 - '-'\n", "170 Kailas Fuga EX BOA - '-'\n", "174 Kailas Fuga Pro 4 - '-'\n", "175 Kailas Fuga EX 2 - '-'\n", "176 Kailas Fuga Elite 2 - '-'\n", "178 Kailas Flythorn Air 2.0 - '-'\n", "180 Nike Pegasus Trail 4 - '-'" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask = df[\"Midsole softness\"].astype(str).str.strip() == \"-\"\n", "df.loc[mask, [\"Brand\",\"Name\", \"Midsole softness\"]].assign(\n", " midsole_repr=df.loc[mask, \"Midsole softness\"].apply(repr)\n", ")" ] }, { "cell_type": "code", "execution_count": 49, "id": "aa55a067", "metadata": {}, "outputs": [], "source": [ "soft_ohe = pd.get_dummies(df[\"Midsole softness\"], prefix=\"midsole\").astype(int)\n", "\n", "# pastikan kolom konsisten untuk pipeline\n", "for col in [\"midsole_Soft\", \"midsole_Balanced\", \"midsole_Firm\"]:\n", " if col not in soft_ohe.columns:\n", " soft_ohe[col] = 0\n", "\n", "# jujur enakan lowercase\n", "soft_ohe = soft_ohe.rename(columns={\n", " \"midsole_Soft\": \"midsole_soft\",\n", " \"midsole_Balanced\": \"midsole_balanced\",\n", " \"midsole_Firm\": \"midsole_firm\"\n", "})\n" ] }, { "cell_type": "code", "execution_count": 50, "id": "3bec47b3", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeMidsole softnessPlateToebox durabilityHeel padding durability...arch_stabilityStrike_normstrike_forefootstrike_heelstrike_middrop_lab_mmdrop_brand_mmmidsole_softmidsole_balancedmidsole_firm
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeBalanced0GoodGood...0Mid|Forefoot1010.38.0010
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to size-0--...0Heel|Mid|Forefoot1118.28.0000
2AltraExperience Wild88\\n Great!$1450True to sizeSoft0DecentDecent...0Mid|Forefoot1014.34.0100
3AltraExperience Wild 279\\n Good!$1400-Balanced0DecentGood...0Mid|Forefoot1016.14.0010
4AltraLone Peak 5.091\\n Superb!$1300True to size-Rock plate--...0Mid|Forefoot1010.20.0000
\n", "

5 rows × 44 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Midsole softness Plate Toebox durability \\\n", "0 Slightly large Balanced 0 Good \n", "1 True to size - 0 - \n", "2 True to size Soft 0 Decent \n", "3 - Balanced 0 Decent \n", "4 True to size - Rock plate - \n", "\n", " Heel padding durability ... arch_stability Strike_norm \\\n", "0 Good ... 0 Mid|Forefoot \n", "1 - ... 0 Heel|Mid|Forefoot \n", "2 Decent ... 0 Mid|Forefoot \n", "3 Good ... 0 Mid|Forefoot \n", "4 - ... 0 Mid|Forefoot \n", "\n", " strike_forefoot strike_heel strike_mid drop_lab_mm drop_brand_mm \\\n", "0 1 0 1 0.3 8.0 \n", "1 1 1 1 8.2 8.0 \n", "2 1 0 1 4.3 4.0 \n", "3 1 0 1 6.1 4.0 \n", "4 1 0 1 0.2 0.0 \n", "\n", " midsole_soft midsole_balanced midsole_firm \n", "0 0 1 0 \n", "1 0 0 0 \n", "2 1 0 0 \n", "3 0 1 0 \n", "4 0 0 0 \n", "\n", "[5 rows x 44 columns]" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.concat([df, soft_ohe[[\"midsole_soft\",\"midsole_balanced\",\"midsole_firm\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 51, "id": "0f0b4517", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 183\n", "Soft: 68\n", "Balanced: 74\n", "Firm: 15\n", "Missing midsole softness rows: 26\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"Soft:\", int(df[\"midsole_soft\"].sum()))\n", "print(\"Balanced:\", int(df[\"midsole_balanced\"].sum()))\n", "print(\"Firm:\", int(df[\"midsole_firm\"].sum()))\n", "\n", "missing_midsole = (df[[\"midsole_soft\",\"midsole_balanced\",\"midsole_firm\"]].sum(axis=1) == 0).sum()\n", "print(\"Missing midsole softness rows:\", int(missing_midsole))" ] }, { "cell_type": "code", "execution_count": 52, "id": "0ba8bc2f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Midsole softness midsole_soft midsole_balanced midsole_firm\n", "0 Balanced 0 1 0\n", "1 - 0 0 0\n", "2 Soft 1 0 0\n", "3 Balanced 0 1 0\n", "4 - 0 0 0\n" ] } ], "source": [ "print(df[[\"Midsole softness\", \"midsole_soft\", \"midsole_balanced\", \"midsole_firm\"]].head())" ] }, { "cell_type": "code", "execution_count": 53, "id": "6c9577e7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 43 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Plate 180 non-null str \n", " 7 Toebox durability 181 non-null str \n", " 8 Heel padding durability 181 non-null str \n", " 9 Outsole durability 181 non-null str \n", " 10 Breathability 181 non-null str \n", " 11 Width / fit 181 non-null str \n", " 12 Toebox width 181 non-null str \n", " 13 Stiffness 181 non-null str \n", " 14 Torsional rigidity 181 non-null str \n", " 15 Heel counter stiffness 181 non-null str \n", " 16 Lug depth 181 non-null str \n", " 17 Heel stack lab Heel stack brand 181 non-null str \n", " 18 Forefoot lab Forefoot brand 181 non-null str \n", " 19 Widths available 181 non-null str \n", " 20 For heavy runners 181 non-null str \n", " 21 Season 181 non-null str \n", " 22 Removable insole 181 non-null str \n", " 23 Orthotic friendly 181 non-null str \n", " 24 Waterproofing 180 non-null str \n", " 25 Ranking 181 non-null str \n", " 26 Popularity 181 non-null str \n", " 27 terrain_norm 181 non-null str \n", " 28 terrain_light 183 non-null int64 \n", " 29 terrain_moderate 183 non-null int64 \n", " 30 terrain_technical 183 non-null int64 \n", " 31 Arch_grouped 181 non-null str \n", " 32 arch_neutral 183 non-null int64 \n", " 33 arch_stability 183 non-null int64 \n", " 34 Strike_norm 181 non-null str \n", " 35 strike_forefoot 183 non-null int64 \n", " 36 strike_heel 183 non-null int64 \n", " 37 strike_mid 183 non-null int64 \n", " 38 drop_lab_mm 181 non-null float64\n", " 39 drop_brand_mm 174 non-null float64\n", " 40 midsole_soft 183 non-null int64 \n", " 41 midsole_balanced 183 non-null int64 \n", " 42 midsole_firm 183 non-null int64 \n", "dtypes: float64(2), int64(11), str(30)\n", "memory usage: 61.6 KB\n" ] } ], "source": [ "df.drop(columns=[\"Midsole softness\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "2d07928e", "metadata": {}, "source": [ "# Plate" ] }, { "cell_type": "code", "execution_count": 54, "id": "2dae17bb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['0', 'Rock plate', 'Carbon plate', nan]\n", "Length: 4, dtype: str\n" ] } ], "source": [ "print(df[\"Plate\"].unique())" ] }, { "cell_type": "code", "execution_count": 60, "id": "4e624338", "metadata": {}, "outputs": [], "source": [ "# df = df.loc[:, ~df.columns.duplicated()]\n", "\n", "# temp_plate = (\n", "# df[\"Plate\"]\n", "# .astype(str)\n", "# .str.strip()\n", "# .str.replace(r\"\\s+\", \" \", regex=True)\n", "# .str.title()\n", "# )\n", "\n", "# plate_ohe = pd.get_dummies(temp_plate, prefix=\"plate\").astype(int)\n", "\n", "# mapping = {\n", "# \"plate_Carbon Plate\": \"plate_carbon\",\n", "# \"plate_Rock Plate\": \"plate_rock\",\n", "# \"plate_0\": \"plate_none\"\n", "# }\n", "\n", "# plate_ohe = plate_ohe.rename(columns=mapping)\n", "\n", "# target_cols = [\"plate_carbon\", \"plate_rock\", \"plate_none\"]\n", "\n", "\n", "# for col in target_cols:\n", "# if col not in plate_ohe.columns:\n", "# plate_ohe[col] = 0\n", "\n", "\n", "# df = df.drop(columns=[c for c in target_cols if c in df.columns])\n", "\n", "\n", "# df = pd.concat([df, plate_ohe[target_cols]], axis=1)\n", "\n", "\n", "# print(\"Sampel Plate '0':\")\n", "# print(df[df[\"Plate\"] == \"0\"][[\"Plate\"] + target_cols].head(2))\n", "\n", "# print(\"\\nSampel Plate 'NaN' atau '-':\")\n", "# mask_null = df[\"Plate\"].isna() | df[\"Plate\"].isin([\"-\", \"nan\", \"Nan\"])\n", "# print(df[mask_null][[\"Plate\"] + target_cols].head(2))" ] }, { "cell_type": "code", "execution_count": 61, "id": "26a50bd1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 45 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Toebox durability 181 non-null str \n", " 7 Heel padding durability 181 non-null str \n", " 8 Outsole durability 181 non-null str \n", " 9 Breathability 181 non-null str \n", " 10 Width / fit 181 non-null str \n", " 11 Toebox width 181 non-null str \n", " 12 Stiffness 181 non-null str \n", " 13 Torsional rigidity 181 non-null str \n", " 14 Heel counter stiffness 181 non-null str \n", " 15 Lug depth 181 non-null str \n", " 16 Heel stack lab Heel stack brand 181 non-null str \n", " 17 Forefoot lab Forefoot brand 181 non-null str \n", " 18 Widths available 181 non-null str \n", " 19 For heavy runners 181 non-null str \n", " 20 Season 181 non-null str \n", " 21 Removable insole 181 non-null str \n", " 22 Orthotic friendly 181 non-null str \n", " 23 Waterproofing 180 non-null str \n", " 24 Ranking 181 non-null str \n", " 25 Popularity 181 non-null str \n", " 26 terrain_norm 181 non-null str \n", " 27 terrain_light 183 non-null int64 \n", " 28 terrain_moderate 183 non-null int64 \n", " 29 terrain_technical 183 non-null int64 \n", " 30 Arch_grouped 181 non-null str \n", " 31 arch_neutral 183 non-null int64 \n", " 32 arch_stability 183 non-null int64 \n", " 33 Strike_norm 181 non-null str \n", " 34 strike_forefoot 183 non-null int64 \n", " 35 strike_heel 183 non-null int64 \n", " 36 strike_mid 183 non-null int64 \n", " 37 drop_lab_mm 181 non-null float64\n", " 38 drop_brand_mm 174 non-null float64\n", " 39 midsole_soft 183 non-null int64 \n", " 40 midsole_balanced 183 non-null int64 \n", " 41 midsole_firm 183 non-null int64 \n", " 42 plate_carbon 183 non-null int64 \n", " 43 plate_rock 183 non-null int64 \n", " 44 plate_none 183 non-null int64 \n", "dtypes: float64(2), int64(14), str(29)\n", "memory usage: 64.5 KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 63, "id": "7bb1e26e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 45 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Toebox durability 181 non-null str \n", " 7 Heel padding durability 181 non-null str \n", " 8 Outsole durability 181 non-null str \n", " 9 Breathability 181 non-null str \n", " 10 Width / fit 181 non-null str \n", " 11 Toebox width 181 non-null str \n", " 12 Stiffness 181 non-null str \n", " 13 Torsional rigidity 181 non-null str \n", " 14 Heel counter stiffness 181 non-null str \n", " 15 Lug depth 181 non-null str \n", " 16 Heel stack lab Heel stack brand 181 non-null str \n", " 17 Forefoot lab Forefoot brand 181 non-null str \n", " 18 Widths available 181 non-null str \n", " 19 For heavy runners 181 non-null str \n", " 20 Season 181 non-null str \n", " 21 Removable insole 181 non-null str \n", " 22 Orthotic friendly 181 non-null str \n", " 23 Waterproofing 180 non-null str \n", " 24 Ranking 181 non-null str \n", " 25 Popularity 181 non-null str \n", " 26 terrain_norm 181 non-null str \n", " 27 terrain_light 183 non-null int64 \n", " 28 terrain_moderate 183 non-null int64 \n", " 29 terrain_technical 183 non-null int64 \n", " 30 Arch_grouped 181 non-null str \n", " 31 arch_neutral 183 non-null int64 \n", " 32 arch_stability 183 non-null int64 \n", " 33 Strike_norm 181 non-null str \n", " 34 strike_forefoot 183 non-null int64 \n", " 35 strike_heel 183 non-null int64 \n", " 36 strike_mid 183 non-null int64 \n", " 37 drop_lab_mm 181 non-null float64\n", " 38 drop_brand_mm 174 non-null float64\n", " 39 midsole_soft 183 non-null int64 \n", " 40 midsole_balanced 183 non-null int64 \n", " 41 midsole_firm 183 non-null int64 \n", " 42 plate_carbon 183 non-null int64 \n", " 43 plate_rock 183 non-null int64 \n", " 44 plate_none 183 non-null int64 \n", "dtypes: float64(2), int64(14), str(29)\n", "memory usage: 64.5 KB\n" ] } ], "source": [ "# df.drop(columns=[\"Plate\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "5452b19f", "metadata": {}, "source": [ "# Toebox durability" ] }, { "cell_type": "code", "execution_count": 65, "id": "dbf23d8e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Toebox (6 uniques): \n", " ['-', 'Bad', 'Decent', 'Good', 'Very Bad', 'Very Good']\n" ] }, { "data": { "text/plain": [ "Toebox durability\n", "- 44\n", "Good 43\n", "Decent 42\n", "Bad 19\n", "Very Bad 18\n", "Very Good 15\n", "Name: count, dtype: int64" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Toebox durability\"] = (\n", " df[\"Toebox durability\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "toebox_uniques = df[\"Toebox durability\"].dropna().unique()\n", "# toebox_uniques.sort()\n", "toebox_uniques = sorted(toebox_uniques)\n", "print(f\"Toebox ({len(toebox_uniques)} uniques): \\n\",toebox_uniques)\n", "\n", "df[\"Toebox durability\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 66, "id": "76cc6296", "metadata": {}, "outputs": [], "source": [ "toe_ohe = pd.get_dummies(df[\"Toebox durability\"], prefix=\"toebox\").astype(int)\n", "\n", "for col in [\"toebox_Bad\", \"toebox_Decent\", \"toebox_Good\"]:\n", " if col not in toe_ohe.columns:\n", " toe_ohe[col] = 0\n", "\n", "toe_ohe = toe_ohe.rename(columns={\n", " \"toebox_Bad\": \"toebox_bad\",\n", " \"toebox_Decent\": \"toebox_decent\",\n", " \"toebox_Good\": \"toebox_good\"\n", "})\n", "\n", "df = pd.concat([df, toe_ohe[[\"toebox_bad\",\"toebox_decent\",\"toebox_good\"]]], axis=1)\n" ] }, { "cell_type": "code", "execution_count": 67, "id": "40fc1dcb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 183\n", "Bad: 19\n", "Decent: 42\n", "Good: 43\n", "Missing toebox rows: 79\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"Bad:\", int(df[\"toebox_bad\"].sum()))\n", "print(\"Decent:\", int(df[\"toebox_decent\"].sum()))\n", "print(\"Good:\", int(df[\"toebox_good\"].sum()))\n", "print(\"Missing toebox rows:\",\n", " int((df[[\"toebox_bad\",\"toebox_decent\",\"toebox_good\"]].sum(axis=1) == 0).sum()))\n" ] }, { "cell_type": "code", "execution_count": 68, "id": "392dbb42", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Toebox durability toebox_decent toebox_bad toebox_good\n", "0 Good 0 0 1\n", "1 - 0 0 0\n", "2 Decent 1 0 0\n", "3 Decent 1 0 0\n", "4 - 0 0 0\n" ] } ], "source": [ "print(df[[\"Toebox durability\", \"toebox_decent\", \"toebox_bad\", \"toebox_good\"]].head())" ] }, { "cell_type": "code", "execution_count": 69, "id": "e683bba3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Good', '-', 'Decent', 'Very Good', 'Bad', 'Very Bad', nan]\n", "Length: 7, dtype: str\n" ] } ], "source": [ "print(df[\"Toebox durability\"].unique())" ] }, { "cell_type": "code", "execution_count": 70, "id": "e295ef0a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 47 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Heel padding durability 181 non-null str \n", " 7 Outsole durability 181 non-null str \n", " 8 Breathability 181 non-null str \n", " 9 Width / fit 181 non-null str \n", " 10 Toebox width 181 non-null str \n", " 11 Stiffness 181 non-null str \n", " 12 Torsional rigidity 181 non-null str \n", " 13 Heel counter stiffness 181 non-null str \n", " 14 Lug depth 181 non-null str \n", " 15 Heel stack lab Heel stack brand 181 non-null str \n", " 16 Forefoot lab Forefoot brand 181 non-null str \n", " 17 Widths available 181 non-null str \n", " 18 For heavy runners 181 non-null str \n", " 19 Season 181 non-null str \n", " 20 Removable insole 181 non-null str \n", " 21 Orthotic friendly 181 non-null str \n", " 22 Waterproofing 180 non-null str \n", " 23 Ranking 181 non-null str \n", " 24 Popularity 181 non-null str \n", " 25 terrain_norm 181 non-null str \n", " 26 terrain_light 183 non-null int64 \n", " 27 terrain_moderate 183 non-null int64 \n", " 28 terrain_technical 183 non-null int64 \n", " 29 Arch_grouped 181 non-null str \n", " 30 arch_neutral 183 non-null int64 \n", " 31 arch_stability 183 non-null int64 \n", " 32 Strike_norm 181 non-null str \n", " 33 strike_forefoot 183 non-null int64 \n", " 34 strike_heel 183 non-null int64 \n", " 35 strike_mid 183 non-null int64 \n", " 36 drop_lab_mm 181 non-null float64\n", " 37 drop_brand_mm 174 non-null float64\n", " 38 midsole_soft 183 non-null int64 \n", " 39 midsole_balanced 183 non-null int64 \n", " 40 midsole_firm 183 non-null int64 \n", " 41 plate_carbon 183 non-null int64 \n", " 42 plate_rock 183 non-null int64 \n", " 43 plate_none 183 non-null int64 \n", " 44 toebox_bad 183 non-null int64 \n", " 45 toebox_decent 183 non-null int64 \n", " 46 toebox_good 183 non-null int64 \n", "dtypes: float64(2), int64(17), str(28)\n", "memory usage: 67.3 KB\n" ] } ], "source": [ "df.drop(columns=[\"Toebox durability\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "1567eabc", "metadata": {}, "source": [ "# Heelpad" ] }, { "cell_type": "code", "execution_count": 72, "id": "1b350a6d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Heel padding (4 uniques): \n", " ['-', 'Bad', 'Decent', 'Good']\n" ] }, { "data": { "text/plain": [ "Heel padding durability\n", "Good 59\n", "Decent 52\n", "- 46\n", "Bad 24\n", "Name: count, dtype: int64" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Heel padding durability\"] = (\n", " df[\"Heel padding durability\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "heel_padding_uniques = df[\"Heel padding durability\"].dropna().unique()\n", "# heel_padding_uniques.sort()\n", "heel_padding_uniques = sorted(heel_padding_uniques)\n", "print(f\"Heel padding ({len(heel_padding_uniques)} uniques): \\n\",heel_padding_uniques)\n", "\n", "df[\"Heel padding durability\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 73, "id": "75fb7094", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeHeel padding durabilityOutsole durabilityBreathabilityWidth / fit...midsole_firmplate_carbonplate_rockplate_nonetoebox_badtoebox_decenttoebox_goodheelpad_badheelpad_decentheelpad_good
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeGoodDecentModerateMedium...0001001001
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to size---Narrow...0001000000
2AltraExperience Wild88\\n Great!$1450True to sizeDecentGoodModerateWide...0001010010
3AltraExperience Wild 279\\n Good!$1400-GoodGoodWarmWide...0001010001
4AltraLone Peak 5.091\\n Superb!$1300True to size---Narrow...0010000000
\n", "

5 rows × 50 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Heel padding durability Outsole durability Breathability \\\n", "0 Slightly large Good Decent Moderate \n", "1 True to size - - - \n", "2 True to size Decent Good Moderate \n", "3 - Good Good Warm \n", "4 True to size - - - \n", "\n", " Width / fit ... midsole_firm plate_carbon plate_rock plate_none toebox_bad \\\n", "0 Medium ... 0 0 0 1 0 \n", "1 Narrow ... 0 0 0 1 0 \n", "2 Wide ... 0 0 0 1 0 \n", "3 Wide ... 0 0 0 1 0 \n", "4 Narrow ... 0 0 1 0 0 \n", "\n", " toebox_decent toebox_good heelpad_bad heelpad_decent heelpad_good \n", "0 0 1 0 0 1 \n", "1 0 0 0 0 0 \n", "2 1 0 0 1 0 \n", "3 1 0 0 0 1 \n", "4 0 0 0 0 0 \n", "\n", "[5 rows x 50 columns]" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hpd_ohe = pd.get_dummies(df[\"Heel padding durability\"], prefix=\"heel_pad\").astype(int)\n", "\n", "\n", "for col in [\"heel_pad_Bad\", \"heel_pad_Decent\", \"heel_pad_Good\"]:\n", " if col not in hpd_ohe.columns:\n", " hpd_ohe[col] = 0\n", "\n", "\n", "hpd_ohe = hpd_ohe.rename(columns={\n", " \"heel_pad_Bad\": \"heelpad_bad\",\n", " \"heel_pad_Decent\": \"heelpad_decent\",\n", " \"heel_pad_Good\": \"heelpad_good\"\n", "})\n", "\n", "df = pd.concat([df, hpd_ohe[[\"heelpad_bad\", \"heelpad_decent\", \"heelpad_good\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 74, "id": "15f701fb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 183\n", "Bad: 24\n", "Decent: 52\n", "Good: 59\n", "Missing heelpad durability rows: 48\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"Bad:\", int(df[\"heelpad_bad\"].sum()))\n", "print(\"Decent:\", int(df[\"heelpad_decent\"].sum()))\n", "print(\"Good:\", int(df[\"heelpad_good\"].sum()))\n", "print(\"Missing heelpad durability rows:\",\n", " int((df[[\"heelpad_bad\",\"heelpad_decent\",\"heelpad_good\"]].sum(axis=1) == 0).sum()))\n" ] }, { "cell_type": "code", "execution_count": 75, "id": "c92cd1e6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Good', '-', 'Decent', 'Bad', nan]\n", "Length: 5, dtype: str\n" ] } ], "source": [ "print(df[\"Heel padding durability\"].unique())" ] }, { "cell_type": "code", "execution_count": 76, "id": "e394e344", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Heel padding durability heelpad_bad heelpad_decent heelpad_good\n", "0 Good 0 0 1\n", "1 - 0 0 0\n", "2 Decent 0 1 0\n", "3 Good 0 0 1\n", "4 - 0 0 0\n" ] } ], "source": [ "print(df[[\"Heel padding durability\", \"heelpad_bad\", \"heelpad_decent\", \"heelpad_good\"]].head())" ] }, { "cell_type": "code", "execution_count": 77, "id": "690d9045", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 49 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Outsole durability 181 non-null str \n", " 7 Breathability 181 non-null str \n", " 8 Width / fit 181 non-null str \n", " 9 Toebox width 181 non-null str \n", " 10 Stiffness 181 non-null str \n", " 11 Torsional rigidity 181 non-null str \n", " 12 Heel counter stiffness 181 non-null str \n", " 13 Lug depth 181 non-null str \n", " 14 Heel stack lab Heel stack brand 181 non-null str \n", " 15 Forefoot lab Forefoot brand 181 non-null str \n", " 16 Widths available 181 non-null str \n", " 17 For heavy runners 181 non-null str \n", " 18 Season 181 non-null str \n", " 19 Removable insole 181 non-null str \n", " 20 Orthotic friendly 181 non-null str \n", " 21 Waterproofing 180 non-null str \n", " 22 Ranking 181 non-null str \n", " 23 Popularity 181 non-null str \n", " 24 terrain_norm 181 non-null str \n", " 25 terrain_light 183 non-null int64 \n", " 26 terrain_moderate 183 non-null int64 \n", " 27 terrain_technical 183 non-null int64 \n", " 28 Arch_grouped 181 non-null str \n", " 29 arch_neutral 183 non-null int64 \n", " 30 arch_stability 183 non-null int64 \n", " 31 Strike_norm 181 non-null str \n", " 32 strike_forefoot 183 non-null int64 \n", " 33 strike_heel 183 non-null int64 \n", " 34 strike_mid 183 non-null int64 \n", " 35 drop_lab_mm 181 non-null float64\n", " 36 drop_brand_mm 174 non-null float64\n", " 37 midsole_soft 183 non-null int64 \n", " 38 midsole_balanced 183 non-null int64 \n", " 39 midsole_firm 183 non-null int64 \n", " 40 plate_carbon 183 non-null int64 \n", " 41 plate_rock 183 non-null int64 \n", " 42 plate_none 183 non-null int64 \n", " 43 toebox_bad 183 non-null int64 \n", " 44 toebox_decent 183 non-null int64 \n", " 45 toebox_good 183 non-null int64 \n", " 46 heelpad_bad 183 non-null int64 \n", " 47 heelpad_decent 183 non-null int64 \n", " 48 heelpad_good 183 non-null int64 \n", "dtypes: float64(2), int64(20), str(27)\n", "memory usage: 70.2 KB\n" ] } ], "source": [ "df.drop(columns=[\"Heel padding durability\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "7e7bf899", "metadata": {}, "source": [ "# Outsole" ] }, { "cell_type": "code", "execution_count": 79, "id": "27659489", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Outsole (4 uniques): \n", " ['-', 'Bad', 'Decent', 'Good']\n" ] }, { "data": { "text/plain": [ "Outsole durability\n", "Good 85\n", "- 52\n", "Decent 43\n", "Bad 1\n", "Name: count, dtype: int64" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Outsole durability\"] = (\n", " df[\"Outsole durability\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "outsole_uniques = df[\"Outsole durability\"].dropna().unique()\n", "# outsole_uniques.sort()\n", "outsole_uniques = sorted(outsole_uniques)\n", "print(f\"Outsole ({len(outsole_uniques)} uniques): \\n\",outsole_uniques)\n", "\n", "df[\"Outsole durability\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 80, "id": "d81802d4", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeOutsole durabilityBreathabilityWidth / fitToebox width...plate_nonetoebox_badtoebox_decenttoebox_goodheelpad_badheelpad_decentheelpad_goodoutsole_badoutsole_decentoutsole_good
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeDecentModerateMediumNarrow...1001001010
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to size--Narrow-...1000000000
2AltraExperience Wild88\\n Great!$1450True to sizeGoodModerateWideWide...1010010001
3AltraExperience Wild 279\\n Good!$1400-GoodWarmWideWide...1010001001
4AltraLone Peak 5.091\\n Superb!$1300True to size--Narrow-...0000000000
\n", "

5 rows × 52 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Outsole durability Breathability Width / fit Toebox width \\\n", "0 Slightly large Decent Moderate Medium Narrow \n", "1 True to size - - Narrow - \n", "2 True to size Good Moderate Wide Wide \n", "3 - Good Warm Wide Wide \n", "4 True to size - - Narrow - \n", "\n", " ... plate_none toebox_bad toebox_decent toebox_good heelpad_bad \\\n", "0 ... 1 0 0 1 0 \n", "1 ... 1 0 0 0 0 \n", "2 ... 1 0 1 0 0 \n", "3 ... 1 0 1 0 0 \n", "4 ... 0 0 0 0 0 \n", "\n", " heelpad_decent heelpad_good outsole_bad outsole_decent outsole_good \n", "0 0 1 0 1 0 \n", "1 0 0 0 0 0 \n", "2 1 0 0 0 1 \n", "3 0 1 0 0 1 \n", "4 0 0 0 0 0 \n", "\n", "[5 rows x 52 columns]" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "out_ohe = pd.get_dummies(df[\"Outsole durability\"], prefix=\"outsole\").astype(int)\n", "\n", "for col in [\"outsole_Bad\", \"outsole_Decent\", \"outsole_Good\"]:\n", " if col not in out_ohe.columns:\n", " out_ohe[col] = 0\n", "\n", "out_ohe = out_ohe.rename(columns={\n", " \"outsole_Bad\": \"outsole_bad\",\n", " \"outsole_Decent\": \"outsole_decent\",\n", " \"outsole_Good\": \"outsole_good\"\n", "})\n", "\n", "df = pd.concat([df, out_ohe[[\"outsole_bad\",\"outsole_decent\",\"outsole_good\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 81, "id": "17ec6fc9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "outsole_bad 1\n", "outsole_decent 43\n", "outsole_good 85\n", "dtype: int64\n", "Missing outsole rows: 54\n" ] } ], "source": [ "for c in [\"outsole_bad\",\"outsole_decent\",\"outsole_good\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "assert df[[\"outsole_bad\",\"outsole_decent\",\"outsole_good\"]].sum(axis=1).le(1).all()\n", "\n", "print(df[[\"outsole_bad\",\"outsole_decent\",\"outsole_good\"]].sum())\n", "print(\"Missing outsole rows:\",\n", " int((df[[\"outsole_bad\",\"outsole_decent\",\"outsole_good\"]].sum(axis=1) == 0).sum()))" ] }, { "cell_type": "code", "execution_count": 82, "id": "1e7e51c6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Decent', '-', 'Good', 'Bad', nan]\n", "Length: 5, dtype: str\n", " outsole_bad outsole_decent outsole_good Outsole durability\n", "0 0 1 0 Decent\n", "1 0 0 0 -\n", "2 0 0 1 Good\n", "3 0 0 1 Good\n", "4 0 0 0 -\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 51 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Breathability 181 non-null str \n", " 7 Width / fit 181 non-null str \n", " 8 Toebox width 181 non-null str \n", " 9 Stiffness 181 non-null str \n", " 10 Torsional rigidity 181 non-null str \n", " 11 Heel counter stiffness 181 non-null str \n", " 12 Lug depth 181 non-null str \n", " 13 Heel stack lab Heel stack brand 181 non-null str \n", " 14 Forefoot lab Forefoot brand 181 non-null str \n", " 15 Widths available 181 non-null str \n", " 16 For heavy runners 181 non-null str \n", " 17 Season 181 non-null str \n", " 18 Removable insole 181 non-null str \n", " 19 Orthotic friendly 181 non-null str \n", " 20 Waterproofing 180 non-null str \n", " 21 Ranking 181 non-null str \n", " 22 Popularity 181 non-null str \n", " 23 terrain_norm 181 non-null str \n", " 24 terrain_light 183 non-null int64 \n", " 25 terrain_moderate 183 non-null int64 \n", " 26 terrain_technical 183 non-null int64 \n", " 27 Arch_grouped 181 non-null str \n", " 28 arch_neutral 183 non-null int64 \n", " 29 arch_stability 183 non-null int64 \n", " 30 Strike_norm 181 non-null str \n", " 31 strike_forefoot 183 non-null int64 \n", " 32 strike_heel 183 non-null int64 \n", " 33 strike_mid 183 non-null int64 \n", " 34 drop_lab_mm 181 non-null float64\n", " 35 drop_brand_mm 174 non-null float64\n", " 36 midsole_soft 183 non-null int64 \n", " 37 midsole_balanced 183 non-null int64 \n", " 38 midsole_firm 183 non-null int64 \n", " 39 plate_carbon 183 non-null int64 \n", " 40 plate_rock 183 non-null int64 \n", " 41 plate_none 183 non-null int64 \n", " 42 toebox_bad 183 non-null int64 \n", " 43 toebox_decent 183 non-null int64 \n", " 44 toebox_good 183 non-null int64 \n", " 45 heelpad_bad 183 non-null int64 \n", " 46 heelpad_decent 183 non-null int64 \n", " 47 heelpad_good 183 non-null int64 \n", " 48 outsole_bad 183 non-null int64 \n", " 49 outsole_decent 183 non-null int64 \n", " 50 outsole_good 183 non-null int64 \n", "dtypes: float64(2), int64(23), str(26)\n", "memory usage: 73.0 KB\n" ] } ], "source": [ "print(df[\"Outsole durability\"].unique())\n", "\n", "print(df[[\"outsole_bad\", \"outsole_decent\", \"outsole_good\", \"Outsole durability\"]].head())\n", "\n", "df.drop(columns=[\"Outsole durability\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "2c904fbb", "metadata": {}, "source": [ "# Breathability" ] }, { "cell_type": "code", "execution_count": 83, "id": "127dae78", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Moderate', '-', 'Warm', 'Breathable', nan]\n", "Length: 5, dtype: str\n" ] } ], "source": [ "print(df[\"Breathability\"].unique())" ] }, { "cell_type": "code", "execution_count": 85, "id": "eabb5c43", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Breathability (4 uniques): \n", " ['-', 'Breathable', 'Moderate', 'Warm']\n" ] }, { "data": { "text/plain": [ "Breathability\n", "Moderate 102\n", "Warm 39\n", "- 24\n", "Breathable 16\n", "Name: count, dtype: int64" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Breathability\"] = (\n", " df[\"Breathability\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "breathability_uniques = df[\"Breathability\"].dropna().unique()\n", "# breathability_uniques.sort()\n", "breathability_uniques = sorted(breathability_uniques)\n", "print(f\"Breathability ({len(breathability_uniques)} uniques): \\n\",breathability_uniques)\n", "\n", "df[\"Breathability\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 86, "id": "9e10b644", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeBreathabilityWidth / fitToebox widthStiffness...toebox_goodheelpad_badheelpad_decentheelpad_goodoutsole_badoutsole_decentoutsole_goodbreath_breathablebreath_moderatebreath_warm
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeModerateMediumNarrowModerate...1001010010
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to size-Narrow-Stiff...0000000000
2AltraExperience Wild88\\n Great!$1450True to sizeModerateWideWideModerate...0010001010
3AltraExperience Wild 279\\n Good!$1400-WarmWideWideModerate...0001001001
4AltraLone Peak 5.091\\n Superb!$1300True to size-Narrow-Stiff...0000000000
\n", "

5 rows × 54 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Breathability Width / fit Toebox width Stiffness ... \\\n", "0 Slightly large Moderate Medium Narrow Moderate ... \n", "1 True to size - Narrow - Stiff ... \n", "2 True to size Moderate Wide Wide Moderate ... \n", "3 - Warm Wide Wide Moderate ... \n", "4 True to size - Narrow - Stiff ... \n", "\n", " toebox_good heelpad_bad heelpad_decent heelpad_good outsole_bad \\\n", "0 1 0 0 1 0 \n", "1 0 0 0 0 0 \n", "2 0 0 1 0 0 \n", "3 0 0 0 1 0 \n", "4 0 0 0 0 0 \n", "\n", " outsole_decent outsole_good breath_breathable breath_moderate breath_warm \n", "0 1 0 0 1 0 \n", "1 0 0 0 0 0 \n", "2 0 1 0 1 0 \n", "3 0 1 0 0 1 \n", "4 0 0 0 0 0 \n", "\n", "[5 rows x 54 columns]" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "breath_ohe = pd.get_dummies(df[\"Breathability\"], prefix=\"breath\").astype(int)\n", "\n", "for col in [\"breath_Breathable\", \"breath_Moderate\", \"breath_Warm\"]:\n", " if col not in breath_ohe.columns:\n", " breath_ohe[col] = 0\n", "\n", "breath_ohe = breath_ohe.rename(columns={\n", " \"breath_Breathable\": \"breath_breathable\",\n", " \"breath_Moderate\": \"breath_moderate\",\n", " \"breath_Warm\": \"breath_warm\"\n", "})\n", "\n", "df = pd.concat([df, breath_ohe[[\"breath_breathable\",\"breath_moderate\",\"breath_warm\"]]], axis=1)\n", "df.head()\n" ] }, { "cell_type": "code", "execution_count": 87, "id": "7c517e8f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "breath_breathable 16\n", "breath_moderate 102\n", "breath_warm 39\n", "dtype: int64\n", "Missing breathability rows: 26\n" ] } ], "source": [ "for c in [\"breath_breathable\",\"breath_moderate\",\"breath_warm\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "assert df[[\"breath_breathable\",\"breath_moderate\",\"breath_warm\"]].sum(axis=1).le(1).all()\n", "\n", "print(df[[\"breath_breathable\",\"breath_moderate\",\"breath_warm\"]].sum())\n", "print(\"Missing breathability rows:\",\n", " int((df[[\"breath_breathable\",\"breath_moderate\",\"breath_warm\"]].sum(axis=1) == 0).sum()))" ] }, { "cell_type": "code", "execution_count": 88, "id": "3fc80c24", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Moderate', '-', 'Warm', 'Breathable', nan]\n", "Length: 5, dtype: str\n", " Breathability breath_breathable breath_moderate breath_warm\n", "0 Moderate 0 1 0\n", "1 - 0 0 0\n", "2 Moderate 0 1 0\n", "3 Warm 0 0 1\n", "4 - 0 0 0\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 53 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Width / fit 181 non-null str \n", " 7 Toebox width 181 non-null str \n", " 8 Stiffness 181 non-null str \n", " 9 Torsional rigidity 181 non-null str \n", " 10 Heel counter stiffness 181 non-null str \n", " 11 Lug depth 181 non-null str \n", " 12 Heel stack lab Heel stack brand 181 non-null str \n", " 13 Forefoot lab Forefoot brand 181 non-null str \n", " 14 Widths available 181 non-null str \n", " 15 For heavy runners 181 non-null str \n", " 16 Season 181 non-null str \n", " 17 Removable insole 181 non-null str \n", " 18 Orthotic friendly 181 non-null str \n", " 19 Waterproofing 180 non-null str \n", " 20 Ranking 181 non-null str \n", " 21 Popularity 181 non-null str \n", " 22 terrain_norm 181 non-null str \n", " 23 terrain_light 183 non-null int64 \n", " 24 terrain_moderate 183 non-null int64 \n", " 25 terrain_technical 183 non-null int64 \n", " 26 Arch_grouped 181 non-null str \n", " 27 arch_neutral 183 non-null int64 \n", " 28 arch_stability 183 non-null int64 \n", " 29 Strike_norm 181 non-null str \n", " 30 strike_forefoot 183 non-null int64 \n", " 31 strike_heel 183 non-null int64 \n", " 32 strike_mid 183 non-null int64 \n", " 33 drop_lab_mm 181 non-null float64\n", " 34 drop_brand_mm 174 non-null float64\n", " 35 midsole_soft 183 non-null int64 \n", " 36 midsole_balanced 183 non-null int64 \n", " 37 midsole_firm 183 non-null int64 \n", " 38 plate_carbon 183 non-null int64 \n", " 39 plate_rock 183 non-null int64 \n", " 40 plate_none 183 non-null int64 \n", " 41 toebox_bad 183 non-null int64 \n", " 42 toebox_decent 183 non-null int64 \n", " 43 toebox_good 183 non-null int64 \n", " 44 heelpad_bad 183 non-null int64 \n", " 45 heelpad_decent 183 non-null int64 \n", " 46 heelpad_good 183 non-null int64 \n", " 47 outsole_bad 183 non-null int64 \n", " 48 outsole_decent 183 non-null int64 \n", " 49 outsole_good 183 non-null int64 \n", " 50 breath_breathable 183 non-null int64 \n", " 51 breath_moderate 183 non-null int64 \n", " 52 breath_warm 183 non-null int64 \n", "dtypes: float64(2), int64(26), str(25)\n", "memory usage: 75.9 KB\n" ] } ], "source": [ "print(df[\"Breathability\"].unique())\n", "\n", "print(df[[\"Breathability\", \"breath_breathable\", \"breath_moderate\",\"breath_warm\"]].head())\n", "\n", "df.drop(columns=[\"Breathability\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "78bea9cd", "metadata": {}, "source": [ "# Width / Fit" ] }, { "cell_type": "code", "execution_count": 89, "id": "e78e0974", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Medium', 'Narrow', 'Wide', nan]\n", "Length: 4, dtype: str\n" ] } ], "source": [ "print(df[\"Width / fit\"].unique())" ] }, { "cell_type": "code", "execution_count": 91, "id": "f8b15fc4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Width / fit (3 uniques): \n", " ['Medium', 'Narrow', 'Wide']\n" ] }, { "data": { "text/plain": [ "Width / fit\n", "Medium 112\n", "Narrow 51\n", "Wide 18\n", "Name: count, dtype: int64" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Width / fit\"] = (\n", " df[\"Width / fit\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "width_uniques = df[\"Width / fit\"].dropna().unique()\n", "# width_uniques.sort()\n", "width_uniques = sorted(width_uniques)\n", "print(f\"Width / fit ({len(width_uniques)} uniques): \\n\",width_uniques)\n", "\n", "df[\"Width / fit\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 92, "id": "443214dc", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeWidth / fitToebox widthStiffnessTorsional rigidity...heelpad_goodoutsole_badoutsole_decentoutsole_goodbreath_breathablebreath_moderatebreath_warmwidth_narrowwidth_mediumwidth_wide
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeMediumNarrowModerateStiff...1010010010
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to sizeNarrow-StiffFlexible...0000000100
2AltraExperience Wild88\\n Great!$1450True to sizeWideWideModerateStiff...0001010001
3AltraExperience Wild 279\\n Good!$1400-WideWideModerateModerate...1001001001
4AltraLone Peak 5.091\\n Superb!$1300True to sizeNarrow-StiffFlexible...0000000100
\n", "

5 rows × 56 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Width / fit Toebox width Stiffness Torsional rigidity ... \\\n", "0 Slightly large Medium Narrow Moderate Stiff ... \n", "1 True to size Narrow - Stiff Flexible ... \n", "2 True to size Wide Wide Moderate Stiff ... \n", "3 - Wide Wide Moderate Moderate ... \n", "4 True to size Narrow - Stiff Flexible ... \n", "\n", " heelpad_good outsole_bad outsole_decent outsole_good breath_breathable \\\n", "0 1 0 1 0 0 \n", "1 0 0 0 0 0 \n", "2 0 0 0 1 0 \n", "3 1 0 0 1 0 \n", "4 0 0 0 0 0 \n", "\n", " breath_moderate breath_warm width_narrow width_medium width_wide \n", "0 1 0 0 1 0 \n", "1 0 0 1 0 0 \n", "2 1 0 0 0 1 \n", "3 0 1 0 0 1 \n", "4 0 0 1 0 0 \n", "\n", "[5 rows x 56 columns]" ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "width_ohe = pd.get_dummies(df[\"Width / fit\"], prefix=\"width\").astype(int)\n", "\n", "for col in [\"width_Narrow\", \"width_Medium\", \"width_Wide\"]:\n", " if col not in width_ohe.columns:\n", " width_ohe[col] = 0\n", "\n", "width_ohe = width_ohe.rename(columns={\n", " \"width_Narrow\": \"width_narrow\",\n", " \"width_Medium\": \"width_medium\",\n", " \"width_Wide\": \"width_wide\"\n", "})\n", "\n", "df = pd.concat([df, width_ohe[[\"width_narrow\",\"width_medium\",\"width_wide\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 93, "id": "67c6646d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "width_narrow 51\n", "width_medium 112\n", "width_wide 18\n", "dtype: int64\n" ] } ], "source": [ "# for c in [\"width_narrow\",\"width_medium\",\"width_wide\"]:\n", "# assert set(df[c].unique()).issubset({0, 1})\n", "\n", "\n", "# assert (df[[\"width_narrow\",\"width_medium\",\"width_wide\"]].sum(axis=1) == 1).all()\n", "\n", "print(df[[\"width_narrow\",\"width_medium\",\"width_wide\"]].sum())" ] }, { "cell_type": "code", "execution_count": 94, "id": "941f04d5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Medium', 'Narrow', 'Wide', nan]\n", "Length: 4, dtype: str\n", " Width / fit width_narrow width_medium width_wide\n", "0 Medium 0 1 0\n", "1 Narrow 1 0 0\n", "2 Wide 0 0 1\n", "3 Wide 0 0 1\n", "4 Narrow 1 0 0\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 55 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Toebox width 181 non-null str \n", " 7 Stiffness 181 non-null str \n", " 8 Torsional rigidity 181 non-null str \n", " 9 Heel counter stiffness 181 non-null str \n", " 10 Lug depth 181 non-null str \n", " 11 Heel stack lab Heel stack brand 181 non-null str \n", " 12 Forefoot lab Forefoot brand 181 non-null str \n", " 13 Widths available 181 non-null str \n", " 14 For heavy runners 181 non-null str \n", " 15 Season 181 non-null str \n", " 16 Removable insole 181 non-null str \n", " 17 Orthotic friendly 181 non-null str \n", " 18 Waterproofing 180 non-null str \n", " 19 Ranking 181 non-null str \n", " 20 Popularity 181 non-null str \n", " 21 terrain_norm 181 non-null str \n", " 22 terrain_light 183 non-null int64 \n", " 23 terrain_moderate 183 non-null int64 \n", " 24 terrain_technical 183 non-null int64 \n", " 25 Arch_grouped 181 non-null str \n", " 26 arch_neutral 183 non-null int64 \n", " 27 arch_stability 183 non-null int64 \n", " 28 Strike_norm 181 non-null str \n", " 29 strike_forefoot 183 non-null int64 \n", " 30 strike_heel 183 non-null int64 \n", " 31 strike_mid 183 non-null int64 \n", " 32 drop_lab_mm 181 non-null float64\n", " 33 drop_brand_mm 174 non-null float64\n", " 34 midsole_soft 183 non-null int64 \n", " 35 midsole_balanced 183 non-null int64 \n", " 36 midsole_firm 183 non-null int64 \n", " 37 plate_carbon 183 non-null int64 \n", " 38 plate_rock 183 non-null int64 \n", " 39 plate_none 183 non-null int64 \n", " 40 toebox_bad 183 non-null int64 \n", " 41 toebox_decent 183 non-null int64 \n", " 42 toebox_good 183 non-null int64 \n", " 43 heelpad_bad 183 non-null int64 \n", " 44 heelpad_decent 183 non-null int64 \n", " 45 heelpad_good 183 non-null int64 \n", " 46 outsole_bad 183 non-null int64 \n", " 47 outsole_decent 183 non-null int64 \n", " 48 outsole_good 183 non-null int64 \n", " 49 breath_breathable 183 non-null int64 \n", " 50 breath_moderate 183 non-null int64 \n", " 51 breath_warm 183 non-null int64 \n", " 52 width_narrow 183 non-null int64 \n", " 53 width_medium 183 non-null int64 \n", " 54 width_wide 183 non-null int64 \n", "dtypes: float64(2), int64(29), str(24)\n", "memory usage: 78.8 KB\n" ] } ], "source": [ "print(df[\"Width / fit\"].unique())\n", "\n", "print(df[[\"Width / fit\", \"width_narrow\",\"width_medium\",\"width_wide\"]].head())\n", "\n", "df.drop(columns=[\"Width / fit\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "05e199f9", "metadata": {}, "source": [ "# Toebox Witdth" ] }, { "cell_type": "code", "execution_count": 95, "id": "13ec5038", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Narrow', '-', 'Wide', 'Medium', nan]\n", "Length: 5, dtype: str\n" ] } ], "source": [ "print(df[\"Toebox width\"].unique())" ] }, { "cell_type": "code", "execution_count": 97, "id": "0e011a58", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Toebox width (4 uniques): \n", " ['-', 'Medium', 'Narrow', 'Wide']\n" ] }, { "data": { "text/plain": [ "Toebox width\n", "Medium 80\n", "Wide 41\n", "- 39\n", "Narrow 21\n", "Name: count, dtype: int64" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Toebox width\"] = (\n", " df[\"Toebox width\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "toebox_uniques = df[\"Toebox width\"].dropna().unique()\n", "# toebox_uniques.sort()\n", "toebox_uniques = sorted(toebox_uniques)\n", "print(f\"Toebox width ({len(toebox_uniques)} uniques): \\n\",toebox_uniques)\n", "\n", "df[\"Toebox width\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 98, "id": "733f304c", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeToebox widthStiffnessTorsional rigidityHeel counter stiffness...outsole_goodbreath_breathablebreath_moderatebreath_warmwidth_narrowwidth_mediumwidth_widetoeboxwidth_narrowtoeboxwidth_mediumtoeboxwidth_wide
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeNarrowModerateStiffFlexible...0010010100
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to size-StiffFlexibleFlexible...0000100000
2AltraExperience Wild88\\n Great!$1450True to sizeWideModerateStiffModerate...1010001001
3AltraExperience Wild 279\\n Good!$1400-WideModerateModerateFlexible...1001001001
4AltraLone Peak 5.091\\n Superb!$1300True to size-StiffFlexible-...0000100000
\n", "

5 rows × 58 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Toebox width Stiffness Torsional rigidity \\\n", "0 Slightly large Narrow Moderate Stiff \n", "1 True to size - Stiff Flexible \n", "2 True to size Wide Moderate Stiff \n", "3 - Wide Moderate Moderate \n", "4 True to size - Stiff Flexible \n", "\n", " Heel counter stiffness ... outsole_good breath_breathable breath_moderate \\\n", "0 Flexible ... 0 0 1 \n", "1 Flexible ... 0 0 0 \n", "2 Moderate ... 1 0 1 \n", "3 Flexible ... 1 0 0 \n", "4 - ... 0 0 0 \n", "\n", " breath_warm width_narrow width_medium width_wide toeboxwidth_narrow \\\n", "0 0 0 1 0 1 \n", "1 0 1 0 0 0 \n", "2 0 0 0 1 0 \n", "3 1 0 0 1 0 \n", "4 0 1 0 0 0 \n", "\n", " toeboxwidth_medium toeboxwidth_wide \n", "0 0 0 \n", "1 0 0 \n", "2 0 1 \n", "3 0 1 \n", "4 0 0 \n", "\n", "[5 rows x 58 columns]" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tw_ohe = pd.get_dummies(df[\"Toebox width\"], prefix=\"toeboxwidth\").astype(int)\n", "\n", "for col in [\"toeboxwidth_Narrow\", \"toeboxwidth_Medium\", \"toeboxwidth_Wide\"]:\n", " if col not in tw_ohe.columns:\n", " tw_ohe[col] = 0\n", "\n", "tw_ohe = tw_ohe.rename(columns={\n", " \"toeboxwidth_Narrow\": \"toeboxwidth_narrow\",\n", " \"toeboxwidth_Medium\": \"toeboxwidth_medium\",\n", " \"toeboxwidth_Wide\": \"toeboxwidth_wide\"\n", "})\n", "\n", "df = pd.concat([df, tw_ohe[[\"toeboxwidth_narrow\",\"toeboxwidth_medium\",\"toeboxwidth_wide\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 99, "id": "ea5b559b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "toeboxwidth_narrow 21\n", "toeboxwidth_medium 80\n", "toeboxwidth_wide 41\n", "dtype: int64\n", "Missing toebox width rows: 41\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"toeboxwidth_narrow\",\"toeboxwidth_medium\",\"toeboxwidth_wide\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# single-label atau missing\n", "assert df[[\"toeboxwidth_narrow\",\"toeboxwidth_medium\",\"toeboxwidth_wide\"]].sum(axis=1).le(1).all()\n", "\n", "print(df[[\"toeboxwidth_narrow\",\"toeboxwidth_medium\",\"toeboxwidth_wide\"]].sum())\n", "print(\n", " \"Missing toebox width rows:\",\n", " int((df[[\"toeboxwidth_narrow\",\"toeboxwidth_medium\",\"toeboxwidth_wide\"]].sum(axis=1) == 0).sum())\n", ")" ] }, { "cell_type": "code", "execution_count": 100, "id": "a9535476", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Narrow', '-', 'Wide', 'Medium', nan]\n", "Length: 5, dtype: str\n", " Toebox width toeboxwidth_narrow toeboxwidth_medium toeboxwidth_wide\n", "0 Narrow 1 0 0\n", "1 - 0 0 0\n", "2 Wide 0 0 1\n", "3 Wide 0 0 1\n", "4 - 0 0 0\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 57 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Stiffness 181 non-null str \n", " 7 Torsional rigidity 181 non-null str \n", " 8 Heel counter stiffness 181 non-null str \n", " 9 Lug depth 181 non-null str \n", " 10 Heel stack lab Heel stack brand 181 non-null str \n", " 11 Forefoot lab Forefoot brand 181 non-null str \n", " 12 Widths available 181 non-null str \n", " 13 For heavy runners 181 non-null str \n", " 14 Season 181 non-null str \n", " 15 Removable insole 181 non-null str \n", " 16 Orthotic friendly 181 non-null str \n", " 17 Waterproofing 180 non-null str \n", " 18 Ranking 181 non-null str \n", " 19 Popularity 181 non-null str \n", " 20 terrain_norm 181 non-null str \n", " 21 terrain_light 183 non-null int64 \n", " 22 terrain_moderate 183 non-null int64 \n", " 23 terrain_technical 183 non-null int64 \n", " 24 Arch_grouped 181 non-null str \n", " 25 arch_neutral 183 non-null int64 \n", " 26 arch_stability 183 non-null int64 \n", " 27 Strike_norm 181 non-null str \n", " 28 strike_forefoot 183 non-null int64 \n", " 29 strike_heel 183 non-null int64 \n", " 30 strike_mid 183 non-null int64 \n", " 31 drop_lab_mm 181 non-null float64\n", " 32 drop_brand_mm 174 non-null float64\n", " 33 midsole_soft 183 non-null int64 \n", " 34 midsole_balanced 183 non-null int64 \n", " 35 midsole_firm 183 non-null int64 \n", " 36 plate_carbon 183 non-null int64 \n", " 37 plate_rock 183 non-null int64 \n", " 38 plate_none 183 non-null int64 \n", " 39 toebox_bad 183 non-null int64 \n", " 40 toebox_decent 183 non-null int64 \n", " 41 toebox_good 183 non-null int64 \n", " 42 heelpad_bad 183 non-null int64 \n", " 43 heelpad_decent 183 non-null int64 \n", " 44 heelpad_good 183 non-null int64 \n", " 45 outsole_bad 183 non-null int64 \n", " 46 outsole_decent 183 non-null int64 \n", " 47 outsole_good 183 non-null int64 \n", " 48 breath_breathable 183 non-null int64 \n", " 49 breath_moderate 183 non-null int64 \n", " 50 breath_warm 183 non-null int64 \n", " 51 width_narrow 183 non-null int64 \n", " 52 width_medium 183 non-null int64 \n", " 53 width_wide 183 non-null int64 \n", " 54 toeboxwidth_narrow 183 non-null int64 \n", " 55 toeboxwidth_medium 183 non-null int64 \n", " 56 toeboxwidth_wide 183 non-null int64 \n", "dtypes: float64(2), int64(32), str(23)\n", "memory usage: 81.6 KB\n" ] } ], "source": [ "print(df[\"Toebox width\"].unique())\n", "\n", "print(df[[\"Toebox width\", \"toeboxwidth_narrow\",\"toeboxwidth_medium\",\"toeboxwidth_wide\"]].head())\n", "\n", "df.drop(columns=[\"Toebox width\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "004e80e2", "metadata": {}, "source": [ "# Stiffness" ] }, { "cell_type": "code", "execution_count": 101, "id": "c70cdef8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Moderate', 'Stiff', 'Flexible', nan]\n", "Length: 4, dtype: str\n" ] } ], "source": [ "print(df[\"Stiffness\"].unique())" ] }, { "cell_type": "code", "execution_count": 103, "id": "37050473", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stiffness (3 uniques): \n", " ['Flexible', 'Moderate', 'Stiff']\n" ] }, { "data": { "text/plain": [ "Stiffness\n", "Stiff 110\n", "Moderate 65\n", "Flexible 6\n", "Name: count, dtype: int64" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Stiffness\"] = (\n", " df[\"Stiffness\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "stiffness_uniques = df[\"Stiffness\"].dropna().unique()\n", "# stiffness_uniques.sort()\n", "stiffness_uniques = sorted(stiffness_uniques)\n", "print(f\"Stiffness ({len(stiffness_uniques)} uniques): \\n\",stiffness_uniques)\n", "\n", "df[\"Stiffness\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 104, "id": "08aa7453", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeStiffnessTorsional rigidityHeel counter stiffnessLug depth...breath_warmwidth_narrowwidth_mediumwidth_widetoeboxwidth_narrowtoeboxwidth_mediumtoeboxwidth_widestiff_flexiblestiff_moderatestiff_stiff
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeModerateStiffFlexible2.5 mm...0010100010
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to sizeStiffFlexibleFlexible2.6 mm...0100000001
2AltraExperience Wild88\\n Great!$1450True to sizeModerateStiffModerate3.6 mm...0001001010
3AltraExperience Wild 279\\n Good!$1400-ModerateModerateFlexible3.5 mm...1001001010
4AltraLone Peak 5.091\\n Superb!$1300True to sizeStiffFlexible-3.7 mm...0100000001
\n", "

5 rows × 60 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Stiffness Torsional rigidity Heel counter stiffness \\\n", "0 Slightly large Moderate Stiff Flexible \n", "1 True to size Stiff Flexible Flexible \n", "2 True to size Moderate Stiff Moderate \n", "3 - Moderate Moderate Flexible \n", "4 True to size Stiff Flexible - \n", "\n", " Lug depth ... breath_warm width_narrow width_medium width_wide \\\n", "0 2.5 mm ... 0 0 1 0 \n", "1 2.6 mm ... 0 1 0 0 \n", "2 3.6 mm ... 0 0 0 1 \n", "3 3.5 mm ... 1 0 0 1 \n", "4 3.7 mm ... 0 1 0 0 \n", "\n", " toeboxwidth_narrow toeboxwidth_medium toeboxwidth_wide stiff_flexible \\\n", "0 1 0 0 0 \n", "1 0 0 0 0 \n", "2 0 0 1 0 \n", "3 0 0 1 0 \n", "4 0 0 0 0 \n", "\n", " stiff_moderate stiff_stiff \n", "0 1 0 \n", "1 0 1 \n", "2 1 0 \n", "3 1 0 \n", "4 0 1 \n", "\n", "[5 rows x 60 columns]" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stiff_ohe = pd.get_dummies(df[\"Stiffness\"], prefix=\"stiff\").astype(int)\n", "\n", "for col in [\"stiff_Flexible\", \"stiff_Moderate\", \"stiff_Stiff\"]:\n", " if col not in stiff_ohe.columns:\n", " stiff_ohe[col] = 0\n", "\n", "stiff_ohe = stiff_ohe.rename(columns={\n", " \"stiff_Flexible\": \"stiff_flexible\",\n", " \"stiff_Moderate\": \"stiff_moderate\",\n", " \"stiff_Stiff\": \"stiff_stiff\"\n", "})\n", "\n", "df = pd.concat([df, stiff_ohe[[\"stiff_flexible\",\"stiff_moderate\",\"stiff_stiff\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 105, "id": "0c014eba", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "stiff_flexible 6\n", "stiff_moderate 65\n", "stiff_stiff 110\n", "dtype: int64\n", "Missing stiffness rows: 2\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"stiff_flexible\",\"stiff_moderate\",\"stiff_stiff\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# single-label atau missing\n", "assert df[[\"stiff_flexible\",\"stiff_moderate\",\"stiff_stiff\"]].sum(axis=1).le(1).all()\n", "\n", "print(df[[\"stiff_flexible\",\"stiff_moderate\",\"stiff_stiff\"]].sum())\n", "print(\n", " \"Missing stiffness rows:\",\n", " int((df[[\"stiff_flexible\",\"stiff_moderate\",\"stiff_stiff\"]].sum(axis=1) == 0).sum())\n", ")\n" ] }, { "cell_type": "code", "execution_count": 106, "id": "b6f0c746", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Moderate', 'Stiff', 'Flexible', nan]\n", "Length: 4, dtype: str\n", " Stiffness stiff_flexible stiff_moderate stiff_stiff\n", "0 Moderate 0 1 0\n", "1 Stiff 0 0 1\n", "2 Moderate 0 1 0\n", "3 Moderate 0 1 0\n", "4 Stiff 0 0 1\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 59 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Torsional rigidity 181 non-null str \n", " 7 Heel counter stiffness 181 non-null str \n", " 8 Lug depth 181 non-null str \n", " 9 Heel stack lab Heel stack brand 181 non-null str \n", " 10 Forefoot lab Forefoot brand 181 non-null str \n", " 11 Widths available 181 non-null str \n", " 12 For heavy runners 181 non-null str \n", " 13 Season 181 non-null str \n", " 14 Removable insole 181 non-null str \n", " 15 Orthotic friendly 181 non-null str \n", " 16 Waterproofing 180 non-null str \n", " 17 Ranking 181 non-null str \n", " 18 Popularity 181 non-null str \n", " 19 terrain_norm 181 non-null str \n", " 20 terrain_light 183 non-null int64 \n", " 21 terrain_moderate 183 non-null int64 \n", " 22 terrain_technical 183 non-null int64 \n", " 23 Arch_grouped 181 non-null str \n", " 24 arch_neutral 183 non-null int64 \n", " 25 arch_stability 183 non-null int64 \n", " 26 Strike_norm 181 non-null str \n", " 27 strike_forefoot 183 non-null int64 \n", " 28 strike_heel 183 non-null int64 \n", " 29 strike_mid 183 non-null int64 \n", " 30 drop_lab_mm 181 non-null float64\n", " 31 drop_brand_mm 174 non-null float64\n", " 32 midsole_soft 183 non-null int64 \n", " 33 midsole_balanced 183 non-null int64 \n", " 34 midsole_firm 183 non-null int64 \n", " 35 plate_carbon 183 non-null int64 \n", " 36 plate_rock 183 non-null int64 \n", " 37 plate_none 183 non-null int64 \n", " 38 toebox_bad 183 non-null int64 \n", " 39 toebox_decent 183 non-null int64 \n", " 40 toebox_good 183 non-null int64 \n", " 41 heelpad_bad 183 non-null int64 \n", " 42 heelpad_decent 183 non-null int64 \n", " 43 heelpad_good 183 non-null int64 \n", " 44 outsole_bad 183 non-null int64 \n", " 45 outsole_decent 183 non-null int64 \n", " 46 outsole_good 183 non-null int64 \n", " 47 breath_breathable 183 non-null int64 \n", " 48 breath_moderate 183 non-null int64 \n", " 49 breath_warm 183 non-null int64 \n", " 50 width_narrow 183 non-null int64 \n", " 51 width_medium 183 non-null int64 \n", " 52 width_wide 183 non-null int64 \n", " 53 toeboxwidth_narrow 183 non-null int64 \n", " 54 toeboxwidth_medium 183 non-null int64 \n", " 55 toeboxwidth_wide 183 non-null int64 \n", " 56 stiff_flexible 183 non-null int64 \n", " 57 stiff_moderate 183 non-null int64 \n", " 58 stiff_stiff 183 non-null int64 \n", "dtypes: float64(2), int64(35), str(22)\n", "memory usage: 84.5 KB\n" ] } ], "source": [ "print(df[\"Stiffness\"].unique())\n", "\n", "print(df[[\"Stiffness\", \"stiff_flexible\",\"stiff_moderate\",\"stiff_stiff\"]].head())\n", "\n", "df.drop(columns=[\"Stiffness\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "f1bff4bd", "metadata": {}, "source": [ "# Torsional Rigidity" ] }, { "cell_type": "code", "execution_count": 107, "id": "e39cc286", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Stiff', 'Flexible', 'Moderate', '-', nan]\n", "Length: 5, dtype: str\n" ] } ], "source": [ "print(df[\"Torsional rigidity\"].unique())" ] }, { "cell_type": "code", "execution_count": 109, "id": "371b0c25", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Torsional rigidity (4 uniques): \n", " ['-', 'Flexible', 'Moderate', 'Stiff']\n" ] }, { "data": { "text/plain": [ "Torsional rigidity\n", "Stiff 103\n", "Moderate 46\n", "Flexible 26\n", "- 6\n", "Name: count, dtype: int64" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Torsional rigidity\"] = (\n", " df[\"Torsional rigidity\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "torsional_rigidity_uniques = df[\"Torsional rigidity\"].dropna().unique()\n", "# torsional_rigidity_uniques.sort()\n", "torsional_rigidity_uniques = sorted(torsional_rigidity_uniques)\n", "print(f\"Torsional rigidity ({len(torsional_rigidity_uniques)} uniques): \\n\",torsional_rigidity_uniques)\n", "\n", "df[\"Torsional rigidity\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 110, "id": "383815f7", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeTorsional rigidityHeel counter stiffnessLug depthHeel stack lab Heel stack brand...width_widetoeboxwidth_narrowtoeboxwidth_mediumtoeboxwidth_widestiff_flexiblestiff_moderatestiff_stifftorsion_flexibletorsion_moderatetorsion_stiff
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeStiffFlexible2.5 mm30.6 mm 38.0 mm...0100010001
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to sizeFlexibleFlexible2.6 mm32.8 mm 26.0 mm...0000001100
2AltraExperience Wild88\\n Great!$1450True to sizeStiffModerate3.6 mm34.5 mm 34.0 mm...1001010001
3AltraExperience Wild 279\\n Good!$1400-ModerateFlexible3.5 mm32.3 mm 32.0 mm...1001010010
4AltraLone Peak 5.091\\n Superb!$1300True to sizeFlexible-3.7 mm24.5 mm 25.0 mm...0000001100
\n", "

5 rows × 62 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Torsional rigidity Heel counter stiffness Lug depth \\\n", "0 Slightly large Stiff Flexible 2.5 mm \n", "1 True to size Flexible Flexible 2.6 mm \n", "2 True to size Stiff Moderate 3.6 mm \n", "3 - Moderate Flexible 3.5 mm \n", "4 True to size Flexible - 3.7 mm \n", "\n", " Heel stack lab Heel stack brand ... width_wide toeboxwidth_narrow \\\n", "0 30.6 mm 38.0 mm ... 0 1 \n", "1 32.8 mm 26.0 mm ... 0 0 \n", "2 34.5 mm 34.0 mm ... 1 0 \n", "3 32.3 mm 32.0 mm ... 1 0 \n", "4 24.5 mm 25.0 mm ... 0 0 \n", "\n", " toeboxwidth_medium toeboxwidth_wide stiff_flexible stiff_moderate \\\n", "0 0 0 0 1 \n", "1 0 0 0 0 \n", "2 0 1 0 1 \n", "3 0 1 0 1 \n", "4 0 0 0 0 \n", "\n", " stiff_stiff torsion_flexible torsion_moderate torsion_stiff \n", "0 0 0 0 1 \n", "1 1 1 0 0 \n", "2 0 0 0 1 \n", "3 0 0 1 0 \n", "4 1 1 0 0 \n", "\n", "[5 rows x 62 columns]" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tors_ohe = pd.get_dummies(df[\"Torsional rigidity\"], prefix=\"torsion\").astype(int)\n", "\n", "for col in [\"torsion_Flexible\", \"torsion_Moderate\", \"torsion_Stiff\"]:\n", " if col not in tors_ohe.columns:\n", " tors_ohe[col] = 0\n", "\n", "tors_ohe = tors_ohe.rename(columns={\n", " \"torsion_Flexible\": \"torsion_flexible\",\n", " \"torsion_Moderate\": \"torsion_moderate\",\n", " \"torsion_Stiff\": \"torsion_stiff\"\n", "})\n", "\n", "df = pd.concat([df, tors_ohe[[\"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 111, "id": "d7ae7eb4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torsion_flexible 26\n", "torsion_moderate 46\n", "torsion_stiff 103\n", "dtype: int64\n", "Missing torsional rigidity rows: 8\n" ] } ], "source": [ "for c in [\"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "assert df[[\"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]].sum(axis=1).le(1).all()\n", "\n", "print(df[[\"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]].sum())\n", "print(\n", " \"Missing torsional rigidity rows:\",\n", " int((df[[\"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]].sum(axis=1) == 0).sum())\n", ")\n" ] }, { "cell_type": "code", "execution_count": 112, "id": "eefda480", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Stiff', 'Flexible', 'Moderate', '-', nan]\n", "Length: 5, dtype: str\n", " Torsional rigidity torsion_flexible torsion_moderate torsion_stiff\n", "0 Stiff 0 0 1\n", "1 Flexible 1 0 0\n", "2 Stiff 0 0 1\n", "3 Moderate 0 1 0\n", "4 Flexible 1 0 0\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 61 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Heel counter stiffness 181 non-null str \n", " 7 Lug depth 181 non-null str \n", " 8 Heel stack lab Heel stack brand 181 non-null str \n", " 9 Forefoot lab Forefoot brand 181 non-null str \n", " 10 Widths available 181 non-null str \n", " 11 For heavy runners 181 non-null str \n", " 12 Season 181 non-null str \n", " 13 Removable insole 181 non-null str \n", " 14 Orthotic friendly 181 non-null str \n", " 15 Waterproofing 180 non-null str \n", " 16 Ranking 181 non-null str \n", " 17 Popularity 181 non-null str \n", " 18 terrain_norm 181 non-null str \n", " 19 terrain_light 183 non-null int64 \n", " 20 terrain_moderate 183 non-null int64 \n", " 21 terrain_technical 183 non-null int64 \n", " 22 Arch_grouped 181 non-null str \n", " 23 arch_neutral 183 non-null int64 \n", " 24 arch_stability 183 non-null int64 \n", " 25 Strike_norm 181 non-null str \n", " 26 strike_forefoot 183 non-null int64 \n", " 27 strike_heel 183 non-null int64 \n", " 28 strike_mid 183 non-null int64 \n", " 29 drop_lab_mm 181 non-null float64\n", " 30 drop_brand_mm 174 non-null float64\n", " 31 midsole_soft 183 non-null int64 \n", " 32 midsole_balanced 183 non-null int64 \n", " 33 midsole_firm 183 non-null int64 \n", " 34 plate_carbon 183 non-null int64 \n", " 35 plate_rock 183 non-null int64 \n", " 36 plate_none 183 non-null int64 \n", " 37 toebox_bad 183 non-null int64 \n", " 38 toebox_decent 183 non-null int64 \n", " 39 toebox_good 183 non-null int64 \n", " 40 heelpad_bad 183 non-null int64 \n", " 41 heelpad_decent 183 non-null int64 \n", " 42 heelpad_good 183 non-null int64 \n", " 43 outsole_bad 183 non-null int64 \n", " 44 outsole_decent 183 non-null int64 \n", " 45 outsole_good 183 non-null int64 \n", " 46 breath_breathable 183 non-null int64 \n", " 47 breath_moderate 183 non-null int64 \n", " 48 breath_warm 183 non-null int64 \n", " 49 width_narrow 183 non-null int64 \n", " 50 width_medium 183 non-null int64 \n", " 51 width_wide 183 non-null int64 \n", " 52 toeboxwidth_narrow 183 non-null int64 \n", " 53 toeboxwidth_medium 183 non-null int64 \n", " 54 toeboxwidth_wide 183 non-null int64 \n", " 55 stiff_flexible 183 non-null int64 \n", " 56 stiff_moderate 183 non-null int64 \n", " 57 stiff_stiff 183 non-null int64 \n", " 58 torsion_flexible 183 non-null int64 \n", " 59 torsion_moderate 183 non-null int64 \n", " 60 torsion_stiff 183 non-null int64 \n", "dtypes: float64(2), int64(38), str(21)\n", "memory usage: 87.3 KB\n" ] } ], "source": [ "print(df[\"Torsional rigidity\"].unique())\n", "\n", "print(df[[\"Torsional rigidity\", \"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]].head())\n", "\n", "df.drop(columns=[\"Torsional rigidity\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "6b6ebe4f", "metadata": {}, "source": [ "# Heel counter stiffness" ] }, { "cell_type": "code", "execution_count": 114, "id": "f8d673a9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Heel counter stiffness (4 uniques): \n", " ['-', 'Flexible', 'Moderate', 'Stiff']\n" ] }, { "data": { "text/plain": [ "Heel counter stiffness\n", "Moderate 63\n", "Stiff 56\n", "Flexible 54\n", "- 8\n", "Name: count, dtype: int64" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Heel counter stiffness\"] = (\n", " df[\"Heel counter stiffness\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "heel_counter_stiffness_uniques = df[\"Heel counter stiffness\"].dropna().unique()\n", "# heel_counter_stiffness_uniques.sort()\n", "heel_counter_stiffness_uniques = sorted(heel_counter_stiffness_uniques)\n", "print(f\"Heel counter stiffness ({len(heel_counter_stiffness_uniques)} uniques): \\n\",heel_counter_stiffness_uniques)\n", "\n", "df[\"Heel counter stiffness\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 115, "id": "1af82ce0", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeHeel counter stiffnessLug depthHeel stack lab Heel stack brandForefoot lab Forefoot brand...toeboxwidth_widestiff_flexiblestiff_moderatestiff_stifftorsion_flexibletorsion_moderatetorsion_stiffheelcounter_flexibleheelcounter_moderateheelcounter_stiff
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly largeFlexible2.5 mm30.6 mm 38.0 mm30.3 mm 30.0 mm...0010001100
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to sizeFlexible2.6 mm32.8 mm 26.0 mm24.6 mm 18.0 mm...0001100100
2AltraExperience Wild88\\n Great!$1450True to sizeModerate3.6 mm34.5 mm 34.0 mm30.2 mm 30.0 mm...1010001010
3AltraExperience Wild 279\\n Good!$1400-Flexible3.5 mm32.3 mm 32.0 mm26.2 mm 28.0 mm...1010010100
4AltraLone Peak 5.091\\n Superb!$1300True to size-3.7 mm24.5 mm 25.0 mm24.3 mm 25.0 mm...0001100000
\n", "

5 rows × 64 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Heel counter stiffness Lug depth \\\n", "0 Slightly large Flexible 2.5 mm \n", "1 True to size Flexible 2.6 mm \n", "2 True to size Moderate 3.6 mm \n", "3 - Flexible 3.5 mm \n", "4 True to size - 3.7 mm \n", "\n", " Heel stack lab Heel stack brand Forefoot lab Forefoot brand ... \\\n", "0 30.6 mm 38.0 mm 30.3 mm 30.0 mm ... \n", "1 32.8 mm 26.0 mm 24.6 mm 18.0 mm ... \n", "2 34.5 mm 34.0 mm 30.2 mm 30.0 mm ... \n", "3 32.3 mm 32.0 mm 26.2 mm 28.0 mm ... \n", "4 24.5 mm 25.0 mm 24.3 mm 25.0 mm ... \n", "\n", " toeboxwidth_wide stiff_flexible stiff_moderate stiff_stiff torsion_flexible \\\n", "0 0 0 1 0 0 \n", "1 0 0 0 1 1 \n", "2 1 0 1 0 0 \n", "3 1 0 1 0 0 \n", "4 0 0 0 1 1 \n", "\n", " torsion_moderate torsion_stiff heelcounter_flexible heelcounter_moderate \\\n", "0 0 1 1 0 \n", "1 0 0 1 0 \n", "2 0 1 0 1 \n", "3 1 0 1 0 \n", "4 0 0 0 0 \n", "\n", " heelcounter_stiff \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", "\n", "[5 rows x 64 columns]" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hc_ohe = pd.get_dummies(df[\"Heel counter stiffness\"], prefix=\"heelcounter\").astype(int)\n", "\n", "for col in [\"heelcounter_Flexible\", \"heelcounter_Moderate\", \"heelcounter_Stiff\"]:\n", " if col not in hc_ohe.columns:\n", " hc_ohe[col] = 0\n", "\n", "hc_ohe = hc_ohe.rename(columns={\n", " \"heelcounter_Flexible\": \"heelcounter_flexible\",\n", " \"heelcounter_Moderate\": \"heelcounter_moderate\",\n", " \"heelcounter_Stiff\": \"heelcounter_stiff\"\n", "})\n", "\n", "df = pd.concat([df, hc_ohe[[\"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]]], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 116, "id": "b496a864", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "heelcounter_flexible 54\n", "heelcounter_moderate 63\n", "heelcounter_stiff 56\n", "dtype: int64\n", "Missing heel counter rows: 10\n" ] } ], "source": [ "for c in [\"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "assert df[[\"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]].sum(axis=1).le(1).all()\n", "\n", "print(df[[\"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]].sum())\n", "print(\n", " \"Missing heel counter rows:\",\n", " int((df[[\"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]].sum(axis=1) == 0).sum())\n", ")" ] }, { "cell_type": "code", "execution_count": 117, "id": "efeecffb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['Flexible', 'Moderate', '-', 'Stiff', nan]\n", "Length: 5, dtype: str\n", " Heel counter stiffness heelcounter_flexible heelcounter_moderate \\\n", "0 Flexible 1 0 \n", "1 Flexible 1 0 \n", "2 Moderate 0 1 \n", "3 Flexible 1 0 \n", "4 - 0 0 \n", "\n", " heelcounter_stiff \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 63 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Lug depth 181 non-null str \n", " 7 Heel stack lab Heel stack brand 181 non-null str \n", " 8 Forefoot lab Forefoot brand 181 non-null str \n", " 9 Widths available 181 non-null str \n", " 10 For heavy runners 181 non-null str \n", " 11 Season 181 non-null str \n", " 12 Removable insole 181 non-null str \n", " 13 Orthotic friendly 181 non-null str \n", " 14 Waterproofing 180 non-null str \n", " 15 Ranking 181 non-null str \n", " 16 Popularity 181 non-null str \n", " 17 terrain_norm 181 non-null str \n", " 18 terrain_light 183 non-null int64 \n", " 19 terrain_moderate 183 non-null int64 \n", " 20 terrain_technical 183 non-null int64 \n", " 21 Arch_grouped 181 non-null str \n", " 22 arch_neutral 183 non-null int64 \n", " 23 arch_stability 183 non-null int64 \n", " 24 Strike_norm 181 non-null str \n", " 25 strike_forefoot 183 non-null int64 \n", " 26 strike_heel 183 non-null int64 \n", " 27 strike_mid 183 non-null int64 \n", " 28 drop_lab_mm 181 non-null float64\n", " 29 drop_brand_mm 174 non-null float64\n", " 30 midsole_soft 183 non-null int64 \n", " 31 midsole_balanced 183 non-null int64 \n", " 32 midsole_firm 183 non-null int64 \n", " 33 plate_carbon 183 non-null int64 \n", " 34 plate_rock 183 non-null int64 \n", " 35 plate_none 183 non-null int64 \n", " 36 toebox_bad 183 non-null int64 \n", " 37 toebox_decent 183 non-null int64 \n", " 38 toebox_good 183 non-null int64 \n", " 39 heelpad_bad 183 non-null int64 \n", " 40 heelpad_decent 183 non-null int64 \n", " 41 heelpad_good 183 non-null int64 \n", " 42 outsole_bad 183 non-null int64 \n", " 43 outsole_decent 183 non-null int64 \n", " 44 outsole_good 183 non-null int64 \n", " 45 breath_breathable 183 non-null int64 \n", " 46 breath_moderate 183 non-null int64 \n", " 47 breath_warm 183 non-null int64 \n", " 48 width_narrow 183 non-null int64 \n", " 49 width_medium 183 non-null int64 \n", " 50 width_wide 183 non-null int64 \n", " 51 toeboxwidth_narrow 183 non-null int64 \n", " 52 toeboxwidth_medium 183 non-null int64 \n", " 53 toeboxwidth_wide 183 non-null int64 \n", " 54 stiff_flexible 183 non-null int64 \n", " 55 stiff_moderate 183 non-null int64 \n", " 56 stiff_stiff 183 non-null int64 \n", " 57 torsion_flexible 183 non-null int64 \n", " 58 torsion_moderate 183 non-null int64 \n", " 59 torsion_stiff 183 non-null int64 \n", " 60 heelcounter_flexible 183 non-null int64 \n", " 61 heelcounter_moderate 183 non-null int64 \n", " 62 heelcounter_stiff 183 non-null int64 \n", "dtypes: float64(2), int64(41), str(20)\n", "memory usage: 90.2 KB\n" ] } ], "source": [ "print(df[\"Heel counter stiffness\"].unique())\n", "\n", "print(df[[\"Heel counter stiffness\", \"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]].head())\n", "\n", "df.drop(columns=[\"Heel counter stiffness\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "65c2c307", "metadata": {}, "source": [ "# split heel stack lab heel stack brand" ] }, { "cell_type": "code", "execution_count": 118, "id": "afd2ce1d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(2)" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask_missing = (\n", " df[\"Heel stack lab Heel stack brand\"].isna() |\n", " (df[\"Heel stack lab Heel stack brand\"].astype(str).str.strip() == \"-\")\n", ")\n", "mask_missing.sum()" ] }, { "cell_type": "code", "execution_count": 119, "id": "c3f9b5a8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Heel stack lab Heel stack brand heel_lab_mm heel_brand_mm\n", "0 30.6 mm 38.0 mm 30.6 38.0\n", "1 32.8 mm 26.0 mm 32.8 26.0\n", "2 34.5 mm 34.0 mm 34.5 34.0\n", "3 32.3 mm 32.0 mm 32.3 32.0\n", "4 24.5 mm 25.0 mm 24.5 25.0\n" ] } ], "source": [ "Heel = df[\"Heel stack lab Heel stack brand\"].fillna(\"\").str.findall(r\"[\\d.]+\")\n", "\n", "Heel = Heel.apply(lambda x: x if isinstance(x, list) else [])\n", "\n", "heel_df = pd.DataFrame(Heel.tolist(), index=df.index)\n", "\n", "while len(heel_df.columns) < 2:\n", " heel_df[len(heel_df.columns)] = None\n", "\n", "df[[\"heel_lab_mm\", \"heel_brand_mm\"]] = heel_df.iloc[:, :2]\n", "\n", "for col in [\"heel_lab_mm\", \"heel_brand_mm\"]:\n", " df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "print(df[[\"Heel stack lab Heel stack brand\", \"heel_lab_mm\", \"heel_brand_mm\"]].head())" ] }, { "cell_type": "code", "execution_count": 120, "id": "fae30d16", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 64 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Lug depth 181 non-null str \n", " 7 Forefoot lab Forefoot brand 181 non-null str \n", " 8 Widths available 181 non-null str \n", " 9 For heavy runners 181 non-null str \n", " 10 Season 181 non-null str \n", " 11 Removable insole 181 non-null str \n", " 12 Orthotic friendly 181 non-null str \n", " 13 Waterproofing 180 non-null str \n", " 14 Ranking 181 non-null str \n", " 15 Popularity 181 non-null str \n", " 16 terrain_norm 181 non-null str \n", " 17 terrain_light 183 non-null int64 \n", " 18 terrain_moderate 183 non-null int64 \n", " 19 terrain_technical 183 non-null int64 \n", " 20 Arch_grouped 181 non-null str \n", " 21 arch_neutral 183 non-null int64 \n", " 22 arch_stability 183 non-null int64 \n", " 23 Strike_norm 181 non-null str \n", " 24 strike_forefoot 183 non-null int64 \n", " 25 strike_heel 183 non-null int64 \n", " 26 strike_mid 183 non-null int64 \n", " 27 drop_lab_mm 181 non-null float64\n", " 28 drop_brand_mm 174 non-null float64\n", " 29 midsole_soft 183 non-null int64 \n", " 30 midsole_balanced 183 non-null int64 \n", " 31 midsole_firm 183 non-null int64 \n", " 32 plate_carbon 183 non-null int64 \n", " 33 plate_rock 183 non-null int64 \n", " 34 plate_none 183 non-null int64 \n", " 35 toebox_bad 183 non-null int64 \n", " 36 toebox_decent 183 non-null int64 \n", " 37 toebox_good 183 non-null int64 \n", " 38 heelpad_bad 183 non-null int64 \n", " 39 heelpad_decent 183 non-null int64 \n", " 40 heelpad_good 183 non-null int64 \n", " 41 outsole_bad 183 non-null int64 \n", " 42 outsole_decent 183 non-null int64 \n", " 43 outsole_good 183 non-null int64 \n", " 44 breath_breathable 183 non-null int64 \n", " 45 breath_moderate 183 non-null int64 \n", " 46 breath_warm 183 non-null int64 \n", " 47 width_narrow 183 non-null int64 \n", " 48 width_medium 183 non-null int64 \n", " 49 width_wide 183 non-null int64 \n", " 50 toeboxwidth_narrow 183 non-null int64 \n", " 51 toeboxwidth_medium 183 non-null int64 \n", " 52 toeboxwidth_wide 183 non-null int64 \n", " 53 stiff_flexible 183 non-null int64 \n", " 54 stiff_moderate 183 non-null int64 \n", " 55 stiff_stiff 183 non-null int64 \n", " 56 torsion_flexible 183 non-null int64 \n", " 57 torsion_moderate 183 non-null int64 \n", " 58 torsion_stiff 183 non-null int64 \n", " 59 heelcounter_flexible 183 non-null int64 \n", " 60 heelcounter_moderate 183 non-null int64 \n", " 61 heelcounter_stiff 183 non-null int64 \n", " 62 heel_lab_mm 181 non-null float64\n", " 63 heel_brand_mm 166 non-null float64\n", "dtypes: float64(4), int64(41), str(19)\n", "memory usage: 91.6 KB\n" ] } ], "source": [ "df.drop(columns=[\"Heel stack lab Heel stack brand\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "3ae97aa1", "metadata": {}, "source": [ "# split forefoot lab brand" ] }, { "cell_type": "code", "execution_count": 121, "id": "7fe9a60d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(2)" ] }, "execution_count": 121, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask_missing = (\n", " df[\"Forefoot lab Forefoot brand\"].isna() |\n", " (df[\"Forefoot lab Forefoot brand\"].astype(str).str.strip() == \"-\")\n", ")\n", "mask_missing.sum()" ] }, { "cell_type": "code", "execution_count": 122, "id": "ee250ac4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Forefoot lab Forefoot brand forefoot_lab_mm forefoot_brand_mm\n", "0 30.3 mm 30.0 mm 30.3 30.0\n", "1 24.6 mm 18.0 mm 24.6 18.0\n", "2 30.2 mm 30.0 mm 30.2 30.0\n", "3 26.2 mm 28.0 mm 26.2 28.0\n", "4 24.3 mm 25.0 mm 24.3 25.0\n" ] } ], "source": [ "forefoot = df[\"Forefoot lab Forefoot brand\"].fillna(\"\").str.findall(r\"[\\d.]+\")\n", "\n", "forefoot = forefoot.apply(lambda x: x if isinstance(x, list) else [])\n", "\n", "forefoot_df = pd.DataFrame(forefoot.tolist(), index=df.index)\n", "\n", "while len(forefoot_df.columns) < 2:\n", " forefoot_df[len(forefoot_df.columns)] = None\n", "\n", "df[[\"forefoot_lab_mm\", \"forefoot_brand_mm\"]] = forefoot_df.iloc[:, :2]\n", "\n", "for col in [\"forefoot_lab_mm\", \"forefoot_brand_mm\"]:\n", " df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "print(df[[\"Forefoot lab Forefoot brand\", \"forefoot_lab_mm\", \"forefoot_brand_mm\"]].head())" ] }, { "cell_type": "code", "execution_count": 123, "id": "15ee0e59", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 65 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Lug depth 181 non-null str \n", " 7 Widths available 181 non-null str \n", " 8 For heavy runners 181 non-null str \n", " 9 Season 181 non-null str \n", " 10 Removable insole 181 non-null str \n", " 11 Orthotic friendly 181 non-null str \n", " 12 Waterproofing 180 non-null str \n", " 13 Ranking 181 non-null str \n", " 14 Popularity 181 non-null str \n", " 15 terrain_norm 181 non-null str \n", " 16 terrain_light 183 non-null int64 \n", " 17 terrain_moderate 183 non-null int64 \n", " 18 terrain_technical 183 non-null int64 \n", " 19 Arch_grouped 181 non-null str \n", " 20 arch_neutral 183 non-null int64 \n", " 21 arch_stability 183 non-null int64 \n", " 22 Strike_norm 181 non-null str \n", " 23 strike_forefoot 183 non-null int64 \n", " 24 strike_heel 183 non-null int64 \n", " 25 strike_mid 183 non-null int64 \n", " 26 drop_lab_mm 181 non-null float64\n", " 27 drop_brand_mm 174 non-null float64\n", " 28 midsole_soft 183 non-null int64 \n", " 29 midsole_balanced 183 non-null int64 \n", " 30 midsole_firm 183 non-null int64 \n", " 31 plate_carbon 183 non-null int64 \n", " 32 plate_rock 183 non-null int64 \n", " 33 plate_none 183 non-null int64 \n", " 34 toebox_bad 183 non-null int64 \n", " 35 toebox_decent 183 non-null int64 \n", " 36 toebox_good 183 non-null int64 \n", " 37 heelpad_bad 183 non-null int64 \n", " 38 heelpad_decent 183 non-null int64 \n", " 39 heelpad_good 183 non-null int64 \n", " 40 outsole_bad 183 non-null int64 \n", " 41 outsole_decent 183 non-null int64 \n", " 42 outsole_good 183 non-null int64 \n", " 43 breath_breathable 183 non-null int64 \n", " 44 breath_moderate 183 non-null int64 \n", " 45 breath_warm 183 non-null int64 \n", " 46 width_narrow 183 non-null int64 \n", " 47 width_medium 183 non-null int64 \n", " 48 width_wide 183 non-null int64 \n", " 49 toeboxwidth_narrow 183 non-null int64 \n", " 50 toeboxwidth_medium 183 non-null int64 \n", " 51 toeboxwidth_wide 183 non-null int64 \n", " 52 stiff_flexible 183 non-null int64 \n", " 53 stiff_moderate 183 non-null int64 \n", " 54 stiff_stiff 183 non-null int64 \n", " 55 torsion_flexible 183 non-null int64 \n", " 56 torsion_moderate 183 non-null int64 \n", " 57 torsion_stiff 183 non-null int64 \n", " 58 heelcounter_flexible 183 non-null int64 \n", " 59 heelcounter_moderate 183 non-null int64 \n", " 60 heelcounter_stiff 183 non-null int64 \n", " 61 heel_lab_mm 181 non-null float64\n", " 62 heel_brand_mm 166 non-null float64\n", " 63 forefoot_lab_mm 181 non-null float64\n", " 64 forefoot_brand_mm 164 non-null float64\n", "dtypes: float64(6), int64(41), str(18)\n", "memory usage: 93.1 KB\n" ] } ], "source": [ "df.drop(columns=[\"Forefoot lab Forefoot brand\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "code", "execution_count": 124, "id": "3e2e0cea", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 65 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Lug depth 181 non-null str \n", " 7 Widths available 181 non-null str \n", " 8 For heavy runners 181 non-null str \n", " 9 Season 181 non-null str \n", " 10 Removable insole 181 non-null str \n", " 11 Orthotic friendly 181 non-null str \n", " 12 Waterproofing 180 non-null str \n", " 13 Ranking 181 non-null str \n", " 14 Popularity 181 non-null str \n", " 15 terrain_norm 181 non-null str \n", " 16 terrain_light 183 non-null int64 \n", " 17 terrain_moderate 183 non-null int64 \n", " 18 terrain_technical 183 non-null int64 \n", " 19 Arch_grouped 181 non-null str \n", " 20 arch_neutral 183 non-null int64 \n", " 21 arch_stability 183 non-null int64 \n", " 22 Strike_norm 181 non-null str \n", " 23 strike_forefoot 183 non-null int64 \n", " 24 strike_heel 183 non-null int64 \n", " 25 strike_mid 183 non-null int64 \n", " 26 drop_lab_mm 181 non-null float64\n", " 27 drop_brand_mm 174 non-null float64\n", " 28 midsole_soft 183 non-null int64 \n", " 29 midsole_balanced 183 non-null int64 \n", " 30 midsole_firm 183 non-null int64 \n", " 31 plate_carbon 183 non-null int64 \n", " 32 plate_rock 183 non-null int64 \n", " 33 plate_none 183 non-null int64 \n", " 34 toebox_bad 183 non-null int64 \n", " 35 toebox_decent 183 non-null int64 \n", " 36 toebox_good 183 non-null int64 \n", " 37 heelpad_bad 183 non-null int64 \n", " 38 heelpad_decent 183 non-null int64 \n", " 39 heelpad_good 183 non-null int64 \n", " 40 outsole_bad 183 non-null int64 \n", " 41 outsole_decent 183 non-null int64 \n", " 42 outsole_good 183 non-null int64 \n", " 43 breath_breathable 183 non-null int64 \n", " 44 breath_moderate 183 non-null int64 \n", " 45 breath_warm 183 non-null int64 \n", " 46 width_narrow 183 non-null int64 \n", " 47 width_medium 183 non-null int64 \n", " 48 width_wide 183 non-null int64 \n", " 49 toeboxwidth_narrow 183 non-null int64 \n", " 50 toeboxwidth_medium 183 non-null int64 \n", " 51 toeboxwidth_wide 183 non-null int64 \n", " 52 stiff_flexible 183 non-null int64 \n", " 53 stiff_moderate 183 non-null int64 \n", " 54 stiff_stiff 183 non-null int64 \n", " 55 torsion_flexible 183 non-null int64 \n", " 56 torsion_moderate 183 non-null int64 \n", " 57 torsion_stiff 183 non-null int64 \n", " 58 heelcounter_flexible 183 non-null int64 \n", " 59 heelcounter_moderate 183 non-null int64 \n", " 60 heelcounter_stiff 183 non-null int64 \n", " 61 heel_lab_mm 181 non-null float64\n", " 62 heel_brand_mm 166 non-null float64\n", " 63 forefoot_lab_mm 181 non-null float64\n", " 64 forefoot_brand_mm 164 non-null float64\n", "dtypes: float64(6), int64(41), str(18)\n", "memory usage: 93.1 KB\n" ] } ], "source": [ "# df.drop(columns=[\"Widths available\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "6d9cce28", "metadata": {}, "source": [ "# Season" ] }, { "cell_type": "code", "execution_count": 126, "id": "4beb740b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Season (4 uniques): \n", " ['-', 'All Seasons', 'Summerall Seasons', 'Winter']\n" ] }, { "data": { "text/plain": [ "Season\n", "All Seasons 122\n", "- 25\n", "Winter 18\n", "Summerall Seasons 16\n", "Name: count, dtype: int64" ] }, "execution_count": 126, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Season\"] = (\n", " df[\"Season\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "heel_counter_stiffness_uniques = df[\"Season\"].dropna().unique()\n", "# heel_counter_stiffness_uniques.sort()\n", "heel_counter_stiffness_uniques = sorted(heel_counter_stiffness_uniques)\n", "print(f\"Season ({len(heel_counter_stiffness_uniques)} uniques): \\n\",heel_counter_stiffness_uniques)\n", "\n", "df[\"Season\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 127, "id": "af24c27a", "metadata": {}, "outputs": [], "source": [ "season_map = {\n", " \"All Seasons\": \"All\",\n", " \"Summerall Seasons\": \"Summer|All\",\n", " \"Winter\": \"Winter\",\n", " \"-\": pd.NA,\n", "}\n", "\n", "df[\"season_norm\"] = df[\"Season\"].map(season_map)" ] }, { "cell_type": "code", "execution_count": 128, "id": "6e39de7e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UNMAPPED Season values (should be empty):\n", " Series([], Name: count, dtype: int64)\n" ] } ], "source": [ "unmapped = df[df[\"season_norm\"].isna() & df[\"Season\"].ne(\"-\")][\"Season\"].value_counts()\n", "print(\"UNMAPPED Season values (should be empty):\\n\", unmapped)\n", "# assert unmapped.empty" ] }, { "cell_type": "code", "execution_count": 129, "id": "f8b3c169", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Season - norm: (4) uniques\n", " \n", "['All', nan, 'Summer|All', 'Winter']\n", "Length: 4, dtype: str\n", "season_norm\n", "All 122\n", "Winter 18\n", "Summer|All 16\n", "Name: count, dtype: int64\n" ] } ], "source": [ "season_norm_unique = df[\"season_norm\"].unique()\n", "print(f'Season - norm: ({len(season_norm_unique)}) uniques\\n', season_norm_unique)\n", "print(df[\"season_norm\"].value_counts())" ] }, { "cell_type": "code", "execution_count": 130, "id": "fecca795", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameAudience scorePriceLightweightSizeLug depthWidths availableFor heavy runnersSeason...heelcounter_stiffheel_lab_mmheel_brand_mmforefoot_lab_mmforefoot_brand_mmseason_normseason_listseason_allseason_summerseason_winter
0AdidasTerrex Agravic Speed Ultra90\\n Superb!$2200Slightly large2.5 mmNormal0All Seasons...030.638.030.330.0All[All]100
1AdidasTerrex Speed Ultra90\\n Superb!$1600True to size2.6 mmNormal0-...032.826.024.618.0NaNNaN000
2AltraExperience Wild88\\n Great!$1450True to size3.6 mmNormal0All Seasons...034.534.030.230.0All[All]100
3AltraExperience Wild 279\\n Good!$1400-3.5 mmNormal0All Seasons...032.332.026.228.0All[All]100
4AltraLone Peak 5.091\\n Superb!$1300True to size3.7 mmNormal0-...024.525.024.325.0NaNNaN000
\n", "

5 rows × 70 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Lightweight \\\n", "0 Adidas Terrex Agravic Speed Ultra 90\\n Superb! $220 0 \n", "1 Adidas Terrex Speed Ultra 90\\n Superb! $160 0 \n", "2 Altra Experience Wild 88\\n Great! $145 0 \n", "3 Altra Experience Wild 2 79\\n Good! $140 0 \n", "4 Altra Lone Peak 5.0 91\\n Superb! $130 0 \n", "\n", " Size Lug depth Widths available For heavy runners Season \\\n", "0 Slightly large 2.5 mm Normal 0 All Seasons \n", "1 True to size 2.6 mm Normal 0 - \n", "2 True to size 3.6 mm Normal 0 All Seasons \n", "3 - 3.5 mm Normal 0 All Seasons \n", "4 True to size 3.7 mm Normal 0 - \n", "\n", " ... heelcounter_stiff heel_lab_mm heel_brand_mm forefoot_lab_mm \\\n", "0 ... 0 30.6 38.0 30.3 \n", "1 ... 0 32.8 26.0 24.6 \n", "2 ... 0 34.5 34.0 30.2 \n", "3 ... 0 32.3 32.0 26.2 \n", "4 ... 0 24.5 25.0 24.3 \n", "\n", " forefoot_brand_mm season_norm season_list season_all season_summer \\\n", "0 30.0 All [All] 1 0 \n", "1 18.0 NaN NaN 0 0 \n", "2 30.0 All [All] 1 0 \n", "3 28.0 All [All] 1 0 \n", "4 25.0 NaN NaN 0 0 \n", "\n", " season_winter \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", "\n", "[5 rows x 70 columns]" ] }, "execution_count": 130, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"season_list\"] = df[\"season_norm\"].str.split(\"|\")\n", "\n", "season_exploded = df[\"season_list\"].explode()\n", "\n", "season_ohe = (\n", " pd.crosstab(season_exploded.index, season_exploded)\n", " .reindex(df.index, fill_value=0)\n", ")\n", "\n", "season_ohe = season_ohe.rename(columns={\n", " \"All\": \"season_all\",\n", " \"Summer\": \"season_summer\",\n", " \"Winter\": \"season_winter\"\n", "})\n", "\n", "for col in [\"season_all\",\"season_summer\",\"season_winter\"]:\n", " if col not in season_ohe.columns:\n", " season_ohe[col] = 0\n", "\n", "season_ohe = season_ohe[[\"season_all\",\"season_summer\",\"season_winter\"]]\n", "\n", "df = pd.concat([df, season_ohe], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 131, "id": "5cf4a935", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 183\n", "all seasons sum: 138\n", "summer sum: 16\n", "winter sum: 18\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"all seasons sum:\", int(df[\"season_all\"].sum()))\n", "print(\"summer sum:\", int(df[\"season_summer\"].sum()))\n", "print(\"winter sum:\", int(df[\"season_winter\"].sum()))" ] }, { "cell_type": "code", "execution_count": 132, "id": "02dc1854", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Season season_norm season_all season_summer season_winter\n", "12 Summerall Seasons Summer|All 1 1 0\n", "16 Summerall Seasons Summer|All 1 1 0\n", "23 Summerall Seasons Summer|All 1 1 0\n", "27 Summerall Seasons Summer|All 1 1 0\n", "30 Summerall Seasons Summer|All 1 1 0\n" ] } ], "source": [ "print(df[df[\"Season\"]==\"Summerall Seasons\"][\n", " [\"Season\",\"season_norm\",\"season_all\",\"season_summer\",\"season_winter\"]\n", "].head())" ] }, { "cell_type": "code", "execution_count": 133, "id": "e23d6b62", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['All Seasons', '-', 'Summerall Seasons', 'Winter', nan]\n", "Length: 5, dtype: str\n", " Season season_norm season_all season_summer season_winter\n", "0 All Seasons All 1 0 0\n", "1 - NaN 0 0 0\n", "2 All Seasons All 1 0 0\n", "3 All Seasons All 1 0 0\n", "4 - NaN 0 0 0\n", "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 68 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Lug depth 181 non-null str \n", " 7 Widths available 181 non-null str \n", " 8 For heavy runners 181 non-null str \n", " 9 Removable insole 181 non-null str \n", " 10 Orthotic friendly 181 non-null str \n", " 11 Waterproofing 180 non-null str \n", " 12 Ranking 181 non-null str \n", " 13 Popularity 181 non-null str \n", " 14 terrain_norm 181 non-null str \n", " 15 terrain_light 183 non-null int64 \n", " 16 terrain_moderate 183 non-null int64 \n", " 17 terrain_technical 183 non-null int64 \n", " 18 Arch_grouped 181 non-null str \n", " 19 arch_neutral 183 non-null int64 \n", " 20 arch_stability 183 non-null int64 \n", " 21 Strike_norm 181 non-null str \n", " 22 strike_forefoot 183 non-null int64 \n", " 23 strike_heel 183 non-null int64 \n", " 24 strike_mid 183 non-null int64 \n", " 25 drop_lab_mm 181 non-null float64\n", " 26 drop_brand_mm 174 non-null float64\n", " 27 midsole_soft 183 non-null int64 \n", " 28 midsole_balanced 183 non-null int64 \n", " 29 midsole_firm 183 non-null int64 \n", " 30 plate_carbon 183 non-null int64 \n", " 31 plate_rock 183 non-null int64 \n", " 32 plate_none 183 non-null int64 \n", " 33 toebox_bad 183 non-null int64 \n", " 34 toebox_decent 183 non-null int64 \n", " 35 toebox_good 183 non-null int64 \n", " 36 heelpad_bad 183 non-null int64 \n", " 37 heelpad_decent 183 non-null int64 \n", " 38 heelpad_good 183 non-null int64 \n", " 39 outsole_bad 183 non-null int64 \n", " 40 outsole_decent 183 non-null int64 \n", " 41 outsole_good 183 non-null int64 \n", " 42 breath_breathable 183 non-null int64 \n", " 43 breath_moderate 183 non-null int64 \n", " 44 breath_warm 183 non-null int64 \n", " 45 width_narrow 183 non-null int64 \n", " 46 width_medium 183 non-null int64 \n", " 47 width_wide 183 non-null int64 \n", " 48 toeboxwidth_narrow 183 non-null int64 \n", " 49 toeboxwidth_medium 183 non-null int64 \n", " 50 toeboxwidth_wide 183 non-null int64 \n", " 51 stiff_flexible 183 non-null int64 \n", " 52 stiff_moderate 183 non-null int64 \n", " 53 stiff_stiff 183 non-null int64 \n", " 54 torsion_flexible 183 non-null int64 \n", " 55 torsion_moderate 183 non-null int64 \n", " 56 torsion_stiff 183 non-null int64 \n", " 57 heelcounter_flexible 183 non-null int64 \n", " 58 heelcounter_moderate 183 non-null int64 \n", " 59 heelcounter_stiff 183 non-null int64 \n", " 60 heel_lab_mm 181 non-null float64\n", " 61 heel_brand_mm 166 non-null float64\n", " 62 forefoot_lab_mm 181 non-null float64\n", " 63 forefoot_brand_mm 164 non-null float64\n", " 64 season_list 156 non-null object \n", " 65 season_all 183 non-null int64 \n", " 66 season_summer 183 non-null int64 \n", " 67 season_winter 183 non-null int64 \n", "dtypes: float64(6), int64(44), object(1), str(17)\n", "memory usage: 97.3+ KB\n" ] } ], "source": [ "print(df[\"Season\"].unique())\n", "print(df[[\"Season\",\"season_norm\",\"season_all\",\"season_summer\",\"season_winter\"]].head())\n", "\n", "df.drop(columns=[\"Season\", \"season_norm\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "code", "execution_count": 134, "id": "b3ae0fbb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Removable insole For heavy runners Orthotic friendly Waterproofing\n", "0 1 0 1 -\n", "1 1 0 1 -\n", "2 1 0 1 -\n", "3 1 0 1 -\n", "4 1 0 1 -\n" ] } ], "source": [ "print(df[[\"Removable insole\",\"For heavy runners\",\"Orthotic friendly\",\"Waterproofing\"]].head())" ] }, { "cell_type": "markdown", "id": "ba48e879", "metadata": {}, "source": [ "# Waterproofing" ] }, { "cell_type": "code", "execution_count": 135, "id": "ba7c8232", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "['-', 'Waterproof', 'Water repellent', 'WaterproofWater repellent', nan]\n", "Length: 5, dtype: str\n" ] } ], "source": [ "print(df[\"Waterproofing\"].unique())" ] }, { "cell_type": "code", "execution_count": 136, "id": "0ff1cd70", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Pengecekan Hasil Waterproofing:\n", " Waterproofing water_proof water_repellent water_both water_none\n", "0 - 0 0 0 1\n", "1 - 0 0 0 1\n", "2 - 0 0 0 1\n", "3 - 0 0 0 1\n", "4 - 0 0 0 1\n" ] } ], "source": [ "df = df.loc[:, ~df.columns.duplicated()]\n", "\n", "temp_water = (\n", " df[\"Waterproofing\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", ")\n", "\n", "water_ohe = pd.get_dummies(temp_water, prefix=\"water\").astype(int)\n", "\n", "mapping = {\n", " \"water_Waterproof\": \"water_proof\",\n", " \"water_Water repellent\": \"water_repellent\",\n", " \"water_WaterproofWater repellent\": \"water_both\", # atau bisa dipisah nanti\n", " \"water_-\": \"water_none\"\n", "}\n", "\n", "water_ohe = water_ohe.rename(columns=mapping)\n", "\n", "target_cols = [\"water_proof\", \"water_repellent\", \"water_both\", \"water_none\"]\n", "\n", "for col in target_cols:\n", " if col not in water_ohe.columns:\n", " water_ohe[col] = 0\n", "\n", "\n", "df = df.drop(columns=[c for c in target_cols if c in df.columns])\n", "\n", "df = pd.concat([df, water_ohe[target_cols]], axis=1)\n", "\n", "print(\"Pengecekan Hasil Waterproofing:\")\n", "sample_check = df[df[\"Waterproofing\"].isna() | (df[\"Waterproofing\"] == \"-\")].head(5)\n", "print(sample_check[[\"Waterproofing\"] + target_cols])" ] }, { "cell_type": "code", "execution_count": 137, "id": "d7d37364", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Waterproofing water_proof water_repellent water_both water_none\n", "0 - 0 0 0 1\n", "1 - 0 0 0 1\n", "2 - 0 0 0 1\n", "3 - 0 0 0 1\n", "4 - 0 0 0 1\n" ] } ], "source": [ "print(df[[\"Waterproofing\",\"water_proof\", \"water_repellent\", \"water_both\", \"water_none\"]].head())" ] }, { "cell_type": "code", "execution_count": 138, "id": "28da3118", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 183 entries, 0 to 182\n", "Data columns (total 71 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 181 non-null str \n", " 1 Name 182 non-null str \n", " 2 Audience score 179 non-null str \n", " 3 Price 181 non-null str \n", " 4 Lightweight 181 non-null str \n", " 5 Size 181 non-null str \n", " 6 Lug depth 181 non-null str \n", " 7 Widths available 181 non-null str \n", " 8 For heavy runners 181 non-null str \n", " 9 Removable insole 181 non-null str \n", " 10 Orthotic friendly 181 non-null str \n", " 11 Ranking 181 non-null str \n", " 12 Popularity 181 non-null str \n", " 13 terrain_norm 181 non-null str \n", " 14 terrain_light 183 non-null int64 \n", " 15 terrain_moderate 183 non-null int64 \n", " 16 terrain_technical 183 non-null int64 \n", " 17 Arch_grouped 181 non-null str \n", " 18 arch_neutral 183 non-null int64 \n", " 19 arch_stability 183 non-null int64 \n", " 20 Strike_norm 181 non-null str \n", " 21 strike_forefoot 183 non-null int64 \n", " 22 strike_heel 183 non-null int64 \n", " 23 strike_mid 183 non-null int64 \n", " 24 drop_lab_mm 181 non-null float64\n", " 25 drop_brand_mm 174 non-null float64\n", " 26 midsole_soft 183 non-null int64 \n", " 27 midsole_balanced 183 non-null int64 \n", " 28 midsole_firm 183 non-null int64 \n", " 29 plate_carbon 183 non-null int64 \n", " 30 plate_rock 183 non-null int64 \n", " 31 plate_none 183 non-null int64 \n", " 32 toebox_bad 183 non-null int64 \n", " 33 toebox_decent 183 non-null int64 \n", " 34 toebox_good 183 non-null int64 \n", " 35 heelpad_bad 183 non-null int64 \n", " 36 heelpad_decent 183 non-null int64 \n", " 37 heelpad_good 183 non-null int64 \n", " 38 outsole_bad 183 non-null int64 \n", " 39 outsole_decent 183 non-null int64 \n", " 40 outsole_good 183 non-null int64 \n", " 41 breath_breathable 183 non-null int64 \n", " 42 breath_moderate 183 non-null int64 \n", " 43 breath_warm 183 non-null int64 \n", " 44 width_narrow 183 non-null int64 \n", " 45 width_medium 183 non-null int64 \n", " 46 width_wide 183 non-null int64 \n", " 47 toeboxwidth_narrow 183 non-null int64 \n", " 48 toeboxwidth_medium 183 non-null int64 \n", " 49 toeboxwidth_wide 183 non-null int64 \n", " 50 stiff_flexible 183 non-null int64 \n", " 51 stiff_moderate 183 non-null int64 \n", " 52 stiff_stiff 183 non-null int64 \n", " 53 torsion_flexible 183 non-null int64 \n", " 54 torsion_moderate 183 non-null int64 \n", " 55 torsion_stiff 183 non-null int64 \n", " 56 heelcounter_flexible 183 non-null int64 \n", " 57 heelcounter_moderate 183 non-null int64 \n", " 58 heelcounter_stiff 183 non-null int64 \n", " 59 heel_lab_mm 181 non-null float64\n", " 60 heel_brand_mm 166 non-null float64\n", " 61 forefoot_lab_mm 181 non-null float64\n", " 62 forefoot_brand_mm 164 non-null float64\n", " 63 season_list 156 non-null object \n", " 64 season_all 183 non-null int64 \n", " 65 season_summer 183 non-null int64 \n", " 66 season_winter 183 non-null int64 \n", " 67 water_proof 183 non-null int64 \n", " 68 water_repellent 183 non-null int64 \n", " 69 water_both 183 non-null int64 \n", " 70 water_none 183 non-null int64 \n", "dtypes: float64(6), int64(48), object(1), str(16)\n", "memory usage: 101.6+ KB\n" ] } ], "source": [ "df.drop(columns=[\"Waterproofing\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "markdown", "id": "a079d462", "metadata": {}, "source": [ "# remove duplicate" ] }, { "cell_type": "code", "execution_count": 139, "id": "4b9a9ea9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "183\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandName
43HokaMafate Speed 4
44HokaMafate Speed 4
50HokaSpeedgoat 6
82New BalanceFresh Foam X Hierro v9
99NikePegasus Trail 5
110OnCloudsurfer Trail
115SalomonGenesis
117SalomonPulsar Trail
125SalomonSense Ride 5
128SalomonSpeedcross 6 GTX
131SalomonThundercross
135SalomonUltra Glide 2
152SauconyXodus Ultra 4
\n", "
" ], "text/plain": [ " Brand Name\n", "43 Hoka Mafate Speed 4\n", "44 Hoka Mafate Speed 4\n", "50 Hoka Speedgoat 6\n", "82 New Balance Fresh Foam X Hierro v9\n", "99 Nike Pegasus Trail 5\n", "110 On Cloudsurfer Trail\n", "115 Salomon Genesis\n", "117 Salomon Pulsar Trail\n", "125 Salomon Sense Ride 5\n", "128 Salomon Speedcross 6 GTX\n", "131 Salomon Thundercross\n", "135 Salomon Ultra Glide 2\n", "152 Saucony Xodus Ultra 4" ] }, "execution_count": 139, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dup_mask = df.duplicated(subset=[\"Brand\", \"Name\"], keep=\"first\")\n", "print(len(dup_mask))\n", "df.loc[dup_mask, [\"Brand\", \"Name\"]].head(100)" ] }, { "cell_type": "code", "execution_count": 140, "id": "e2ba26dc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before: 183\n", "After : 170\n" ] } ], "source": [ "# sebelum hapus\n", "print(\"Before:\", len(df))\n", "\n", "#hapus\n", "df = df.drop_duplicates(subset=[\"Brand\", \"Name\"], keep=\"first\").reset_index(drop=True)\n", "\n", "print(\"After :\", len(df))\n" ] }, { "cell_type": "code", "execution_count": 141, "id": "b1ff9301", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandName
\n", "
" ], "text/plain": [ "Empty DataFrame\n", "Columns: [Brand, Name]\n", "Index: []" ] }, "execution_count": 141, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dup_mask = df.duplicated(subset=[\"Brand\", \"Name\"], keep=\"first\")\n", "df.loc[dup_mask, [\"Brand\", \"Name\"]].head(20)" ] }, { "cell_type": "markdown", "id": "44f09d23", "metadata": {}, "source": [ "# to csv" ] }, { "cell_type": "code", "execution_count": 142, "id": "445f650f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 170 entries, 0 to 169\n", "Data columns (total 71 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 168 non-null str \n", " 1 Name 169 non-null str \n", " 2 Audience score 166 non-null str \n", " 3 Price 168 non-null str \n", " 4 Lightweight 168 non-null str \n", " 5 Size 168 non-null str \n", " 6 Lug depth 168 non-null str \n", " 7 Widths available 168 non-null str \n", " 8 For heavy runners 168 non-null str \n", " 9 Removable insole 168 non-null str \n", " 10 Orthotic friendly 168 non-null str \n", " 11 Ranking 168 non-null str \n", " 12 Popularity 168 non-null str \n", " 13 terrain_norm 168 non-null str \n", " 14 terrain_light 170 non-null int64 \n", " 15 terrain_moderate 170 non-null int64 \n", " 16 terrain_technical 170 non-null int64 \n", " 17 Arch_grouped 168 non-null str \n", " 18 arch_neutral 170 non-null int64 \n", " 19 arch_stability 170 non-null int64 \n", " 20 Strike_norm 168 non-null str \n", " 21 strike_forefoot 170 non-null int64 \n", " 22 strike_heel 170 non-null int64 \n", " 23 strike_mid 170 non-null int64 \n", " 24 drop_lab_mm 168 non-null float64\n", " 25 drop_brand_mm 161 non-null float64\n", " 26 midsole_soft 170 non-null int64 \n", " 27 midsole_balanced 170 non-null int64 \n", " 28 midsole_firm 170 non-null int64 \n", " 29 plate_carbon 170 non-null int64 \n", " 30 plate_rock 170 non-null int64 \n", " 31 plate_none 170 non-null int64 \n", " 32 toebox_bad 170 non-null int64 \n", " 33 toebox_decent 170 non-null int64 \n", " 34 toebox_good 170 non-null int64 \n", " 35 heelpad_bad 170 non-null int64 \n", " 36 heelpad_decent 170 non-null int64 \n", " 37 heelpad_good 170 non-null int64 \n", " 38 outsole_bad 170 non-null int64 \n", " 39 outsole_decent 170 non-null int64 \n", " 40 outsole_good 170 non-null int64 \n", " 41 breath_breathable 170 non-null int64 \n", " 42 breath_moderate 170 non-null int64 \n", " 43 breath_warm 170 non-null int64 \n", " 44 width_narrow 170 non-null int64 \n", " 45 width_medium 170 non-null int64 \n", " 46 width_wide 170 non-null int64 \n", " 47 toeboxwidth_narrow 170 non-null int64 \n", " 48 toeboxwidth_medium 170 non-null int64 \n", " 49 toeboxwidth_wide 170 non-null int64 \n", " 50 stiff_flexible 170 non-null int64 \n", " 51 stiff_moderate 170 non-null int64 \n", " 52 stiff_stiff 170 non-null int64 \n", " 53 torsion_flexible 170 non-null int64 \n", " 54 torsion_moderate 170 non-null int64 \n", " 55 torsion_stiff 170 non-null int64 \n", " 56 heelcounter_flexible 170 non-null int64 \n", " 57 heelcounter_moderate 170 non-null int64 \n", " 58 heelcounter_stiff 170 non-null int64 \n", " 59 heel_lab_mm 168 non-null float64\n", " 60 heel_brand_mm 153 non-null float64\n", " 61 forefoot_lab_mm 168 non-null float64\n", " 62 forefoot_brand_mm 151 non-null float64\n", " 63 season_list 143 non-null object \n", " 64 season_all 170 non-null int64 \n", " 65 season_summer 170 non-null int64 \n", " 66 season_winter 170 non-null int64 \n", " 67 water_proof 170 non-null int64 \n", " 68 water_repellent 170 non-null int64 \n", " 69 water_both 170 non-null int64 \n", " 70 water_none 170 non-null int64 \n", "dtypes: float64(6), int64(48), object(1), str(16)\n", "memory usage: 94.4+ KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 143, "id": "67c2efb2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 170 entries, 0 to 169\n", "Data columns (total 70 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 168 non-null str \n", " 1 Name 169 non-null str \n", " 2 Audience score 166 non-null str \n", " 3 Price 168 non-null str \n", " 4 Lightweight 168 non-null str \n", " 5 Size 168 non-null str \n", " 6 Lug depth 168 non-null str \n", " 7 Widths available 168 non-null str \n", " 8 For heavy runners 168 non-null str \n", " 9 Removable insole 168 non-null str \n", " 10 Orthotic friendly 168 non-null str \n", " 11 Ranking 168 non-null str \n", " 12 Popularity 168 non-null str \n", " 13 terrain_norm 168 non-null str \n", " 14 terrain_light 170 non-null int64 \n", " 15 terrain_moderate 170 non-null int64 \n", " 16 terrain_technical 170 non-null int64 \n", " 17 Arch_grouped 168 non-null str \n", " 18 arch_neutral 170 non-null int64 \n", " 19 arch_stability 170 non-null int64 \n", " 20 Strike_norm 168 non-null str \n", " 21 strike_forefoot 170 non-null int64 \n", " 22 strike_heel 170 non-null int64 \n", " 23 strike_mid 170 non-null int64 \n", " 24 drop_lab_mm 168 non-null float64\n", " 25 drop_brand_mm 161 non-null float64\n", " 26 midsole_soft 170 non-null int64 \n", " 27 midsole_balanced 170 non-null int64 \n", " 28 midsole_firm 170 non-null int64 \n", " 29 plate_carbon 170 non-null int64 \n", " 30 plate_rock 170 non-null int64 \n", " 31 plate_none 170 non-null int64 \n", " 32 toebox_bad 170 non-null int64 \n", " 33 toebox_decent 170 non-null int64 \n", " 34 toebox_good 170 non-null int64 \n", " 35 heelpad_bad 170 non-null int64 \n", " 36 heelpad_decent 170 non-null int64 \n", " 37 heelpad_good 170 non-null int64 \n", " 38 outsole_bad 170 non-null int64 \n", " 39 outsole_decent 170 non-null int64 \n", " 40 outsole_good 170 non-null int64 \n", " 41 breath_breathable 170 non-null int64 \n", " 42 breath_moderate 170 non-null int64 \n", " 43 breath_warm 170 non-null int64 \n", " 44 width_narrow 170 non-null int64 \n", " 45 width_medium 170 non-null int64 \n", " 46 width_wide 170 non-null int64 \n", " 47 toeboxwidth_narrow 170 non-null int64 \n", " 48 toeboxwidth_medium 170 non-null int64 \n", " 49 toeboxwidth_wide 170 non-null int64 \n", " 50 stiff_flexible 170 non-null int64 \n", " 51 stiff_moderate 170 non-null int64 \n", " 52 stiff_stiff 170 non-null int64 \n", " 53 torsion_flexible 170 non-null int64 \n", " 54 torsion_moderate 170 non-null int64 \n", " 55 torsion_stiff 170 non-null int64 \n", " 56 heelcounter_flexible 170 non-null int64 \n", " 57 heelcounter_moderate 170 non-null int64 \n", " 58 heelcounter_stiff 170 non-null int64 \n", " 59 heel_lab_mm 168 non-null float64\n", " 60 heel_brand_mm 153 non-null float64\n", " 61 forefoot_lab_mm 168 non-null float64\n", " 62 forefoot_brand_mm 151 non-null float64\n", " 63 season_all 170 non-null int64 \n", " 64 season_summer 170 non-null int64 \n", " 65 season_winter 170 non-null int64 \n", " 66 water_proof 170 non-null int64 \n", " 67 water_repellent 170 non-null int64 \n", " 68 water_both 170 non-null int64 \n", " 69 water_none 170 non-null int64 \n", "dtypes: float64(6), int64(48), str(16)\n", "memory usage: 93.1 KB\n" ] } ], "source": [ "df.drop(columns=[\"season_list\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "code", "execution_count": 145, "id": "6e18b1b5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 170 entries, 0 to 169\n", "Data columns (total 70 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 168 non-null str \n", " 1 Name 169 non-null str \n", " 2 Audience score 166 non-null str \n", " 3 Price 168 non-null str \n", " 4 Lightweight 168 non-null str \n", " 5 Size 168 non-null str \n", " 6 Lug depth 168 non-null str \n", " 7 Widths available 168 non-null str \n", " 8 For heavy runners 168 non-null str \n", " 9 Removable insole 168 non-null str \n", " 10 Orthotic friendly 168 non-null str \n", " 11 Ranking 168 non-null str \n", " 12 Popularity 168 non-null str \n", " 13 terrain_norm 168 non-null str \n", " 14 terrain_light 170 non-null int64 \n", " 15 terrain_moderate 170 non-null int64 \n", " 16 terrain_technical 170 non-null int64 \n", " 17 Arch_grouped 168 non-null str \n", " 18 arch_neutral 170 non-null int64 \n", " 19 arch_stability 170 non-null int64 \n", " 20 Strike_norm 168 non-null str \n", " 21 strike_forefoot 170 non-null int64 \n", " 22 strike_heel 170 non-null int64 \n", " 23 strike_mid 170 non-null int64 \n", " 24 drop_lab_mm 168 non-null float64\n", " 25 drop_brand_mm 161 non-null float64\n", " 26 midsole_soft 170 non-null int64 \n", " 27 midsole_balanced 170 non-null int64 \n", " 28 midsole_firm 170 non-null int64 \n", " 29 plate_carbon 170 non-null int64 \n", " 30 plate_rock 170 non-null int64 \n", " 31 plate_none 170 non-null int64 \n", " 32 toebox_bad 170 non-null int64 \n", " 33 toebox_decent 170 non-null int64 \n", " 34 toebox_good 170 non-null int64 \n", " 35 heelpad_bad 170 non-null int64 \n", " 36 heelpad_decent 170 non-null int64 \n", " 37 heelpad_good 170 non-null int64 \n", " 38 outsole_bad 170 non-null int64 \n", " 39 outsole_decent 170 non-null int64 \n", " 40 outsole_good 170 non-null int64 \n", " 41 breath_breathable 170 non-null int64 \n", " 42 breath_moderate 170 non-null int64 \n", " 43 breath_warm 170 non-null int64 \n", " 44 width_narrow 170 non-null int64 \n", " 45 width_medium 170 non-null int64 \n", " 46 width_wide 170 non-null int64 \n", " 47 toeboxwidth_narrow 170 non-null int64 \n", " 48 toeboxwidth_medium 170 non-null int64 \n", " 49 toeboxwidth_wide 170 non-null int64 \n", " 50 stiff_flexible 170 non-null int64 \n", " 51 stiff_moderate 170 non-null int64 \n", " 52 stiff_stiff 170 non-null int64 \n", " 53 torsion_flexible 170 non-null int64 \n", " 54 torsion_moderate 170 non-null int64 \n", " 55 torsion_stiff 170 non-null int64 \n", " 56 heelcounter_flexible 170 non-null int64 \n", " 57 heelcounter_moderate 170 non-null int64 \n", " 58 heelcounter_stiff 170 non-null int64 \n", " 59 heel_lab_mm 168 non-null float64\n", " 60 heel_brand_mm 153 non-null float64\n", " 61 forefoot_lab_mm 168 non-null float64\n", " 62 forefoot_brand_mm 151 non-null float64\n", " 63 season_all 170 non-null int64 \n", " 64 season_summer 170 non-null int64 \n", " 65 season_winter 170 non-null int64 \n", " 66 water_proof 170 non-null int64 \n", " 67 water_repellent 170 non-null int64 \n", " 68 water_both 170 non-null int64 \n", " 69 water_none 170 non-null int64 \n", "dtypes: float64(6), int64(48), str(16)\n", "memory usage: 93.1 KB\n" ] } ], "source": [ "# df.drop(columns=[\"weight_lab_g\", \"weight_brand_g\", \"weight_brand_oz\", \"drop_brand_mm\", \"heel_brand_mm\", \"forefoot_brand_mm\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "code", "execution_count": 146, "id": "24ed1981", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 170 entries, 0 to 169\n", "Data columns (total 68 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 168 non-null str \n", " 1 Name 169 non-null str \n", " 2 Lightweight 168 non-null str \n", " 3 Size 168 non-null str \n", " 4 Lug depth 168 non-null str \n", " 5 Widths available 168 non-null str \n", " 6 For heavy runners 168 non-null str \n", " 7 Removable insole 168 non-null str \n", " 8 Orthotic friendly 168 non-null str \n", " 9 Ranking 168 non-null str \n", " 10 Popularity 168 non-null str \n", " 11 terrain_norm 168 non-null str \n", " 12 terrain_light 170 non-null int64 \n", " 13 terrain_moderate 170 non-null int64 \n", " 14 terrain_technical 170 non-null int64 \n", " 15 Arch_grouped 168 non-null str \n", " 16 arch_neutral 170 non-null int64 \n", " 17 arch_stability 170 non-null int64 \n", " 18 Strike_norm 168 non-null str \n", " 19 strike_forefoot 170 non-null int64 \n", " 20 strike_heel 170 non-null int64 \n", " 21 strike_mid 170 non-null int64 \n", " 22 drop_lab_mm 168 non-null float64\n", " 23 drop_brand_mm 161 non-null float64\n", " 24 midsole_soft 170 non-null int64 \n", " 25 midsole_balanced 170 non-null int64 \n", " 26 midsole_firm 170 non-null int64 \n", " 27 plate_carbon 170 non-null int64 \n", " 28 plate_rock 170 non-null int64 \n", " 29 plate_none 170 non-null int64 \n", " 30 toebox_bad 170 non-null int64 \n", " 31 toebox_decent 170 non-null int64 \n", " 32 toebox_good 170 non-null int64 \n", " 33 heelpad_bad 170 non-null int64 \n", " 34 heelpad_decent 170 non-null int64 \n", " 35 heelpad_good 170 non-null int64 \n", " 36 outsole_bad 170 non-null int64 \n", " 37 outsole_decent 170 non-null int64 \n", " 38 outsole_good 170 non-null int64 \n", " 39 breath_breathable 170 non-null int64 \n", " 40 breath_moderate 170 non-null int64 \n", " 41 breath_warm 170 non-null int64 \n", " 42 width_narrow 170 non-null int64 \n", " 43 width_medium 170 non-null int64 \n", " 44 width_wide 170 non-null int64 \n", " 45 toeboxwidth_narrow 170 non-null int64 \n", " 46 toeboxwidth_medium 170 non-null int64 \n", " 47 toeboxwidth_wide 170 non-null int64 \n", " 48 stiff_flexible 170 non-null int64 \n", " 49 stiff_moderate 170 non-null int64 \n", " 50 stiff_stiff 170 non-null int64 \n", " 51 torsion_flexible 170 non-null int64 \n", " 52 torsion_moderate 170 non-null int64 \n", " 53 torsion_stiff 170 non-null int64 \n", " 54 heelcounter_flexible 170 non-null int64 \n", " 55 heelcounter_moderate 170 non-null int64 \n", " 56 heelcounter_stiff 170 non-null int64 \n", " 57 heel_lab_mm 168 non-null float64\n", " 58 heel_brand_mm 153 non-null float64\n", " 59 forefoot_lab_mm 168 non-null float64\n", " 60 forefoot_brand_mm 151 non-null float64\n", " 61 season_all 170 non-null int64 \n", " 62 season_summer 170 non-null int64 \n", " 63 season_winter 170 non-null int64 \n", " 64 water_proof 170 non-null int64 \n", " 65 water_repellent 170 non-null int64 \n", " 66 water_both 170 non-null int64 \n", " 67 water_none 170 non-null int64 \n", "dtypes: float64(6), int64(48), str(14)\n", "memory usage: 90.4 KB\n" ] } ], "source": [ "df.drop(columns=[\"Audience score\", \"Price\"], inplace=True)\n", "df.info()" ] }, { "cell_type": "code", "execution_count": 148, "id": "8d080857", "metadata": {}, "outputs": [], "source": [ "df.to_csv('../../data/trail_dataset.csv', index=False)" ] } ], "metadata": { "kernelspec": { "display_name": "env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.11" } }, "nbformat": 4, "nbformat_minor": 5 }