{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "4944982d", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Heel lab Heel brandForefoot lab Forefoot brandWidths availableOrthotic friendlySeasonRemovable insoleRankingPopularityGenderTerrain
0BrooksLaunch 987\\n Great!$110Daily runningTempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelMid/forefoot...32.4 mm 36.0 mm23.0 mm 26.0 mmNormalWide1-1#301 Top 47%#352 Bottom 45%NaNNaN
1BrooksLevitate 690\\n Superb!$150Daily runningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/forefoot...34.3 mm 32.5 mm26.6 mm 24.5 mmNormal1SummerAll seasons1#72 Top 20%#255 Bottom 30%NaNNaN
2Adidas4DFWD90\\n Superb!$200Daily runningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelMid/forefoot...33.3 mm 32.5 mm24.4 mm 22.5 mmNormal1All seasons1#104 Top 17%#368 Bottom 42%NaNNaN
3Adidas4DFWD 290\\n Superb!$200Daily runningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...31.8 mm 32.0 mm21.2 mm 21.0 mmNormal1All seasons1#126 Top 20%#541 Bottom 16%NaNNaN
4Adidas4DFWD 388\\n Great!$200Daily runningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelMid/forefoot...32.6 mm 34.0 mm22.7 mm 24.0 mmNormal1All seasons1#116 Top 32%#339 Bottom 7%NaNNaN
\n", "

5 rows × 33 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily runningTempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Heel lab Heel brand Forefoot lab Forefoot brand \\\n", "0 HeelMid/forefoot ... 32.4 mm 36.0 mm 23.0 mm 26.0 mm \n", "1 Mid/forefoot ... 34.3 mm 32.5 mm 26.6 mm 24.5 mm \n", "2 HeelMid/forefoot ... 33.3 mm 32.5 mm 24.4 mm 22.5 mm \n", "3 Heel ... 31.8 mm 32.0 mm 21.2 mm 21.0 mm \n", "4 HeelMid/forefoot ... 32.6 mm 34.0 mm 22.7 mm 24.0 mm \n", "\n", " Widths available Orthotic friendly Season Removable insole \\\n", "0 NormalWide 1 - 1 \n", "1 Normal 1 SummerAll seasons 1 \n", "2 Normal 1 All seasons 1 \n", "3 Normal 1 All seasons 1 \n", "4 Normal 1 All seasons 1 \n", "\n", " Ranking Popularity Gender Terrain \n", "0 #301 Top 47% #352 Bottom 45% NaN NaN \n", "1 #72 Top 20% #255 Bottom 30% NaN NaN \n", "2 #104 Top 17% #368 Bottom 42% NaN NaN \n", "3 #126 Top 20% #541 Bottom 16% NaN NaN \n", "4 #116 Top 32% #339 Bottom 7% NaN NaN \n", "\n", "[5 rows x 33 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "df = pd.read_csv('../../data/SONIX utilities - Road.csv')\n", "df.head()" ] }, { "cell_type": "markdown", "id": "1d066ba9", "metadata": {}, "source": [ "value \"✗\" sama \"✓\" udah diubah ke 0 1 manual di sheet" ] }, { "cell_type": "code", "execution_count": 2, "id": "bc8a931f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 1170 entries, 0 to 1169\n", "Data columns (total 33 columns):\n", " # Column Non-Null Count Dtype\n", "--- ------ -------------- -----\n", " 0 Brand 1170 non-null str \n", " 1 Name 1170 non-null str \n", " 2 Audience score 1164 non-null str \n", " 3 Price 1170 non-null str \n", " 4 Pace 1170 non-null str \n", " 5 Arch support 1170 non-null str \n", " 6 Weight lab Weight brand 1170 non-null str \n", " 7 Lightweight 1170 non-null int64\n", " 8 Drop lab Drop brand 1170 non-null str \n", " 9 Strike pattern 1170 non-null str \n", " 10 Size 1170 non-null str \n", " 11 Midsole softness 1170 non-null str \n", " 12 Toebox durability 1170 non-null str \n", " 13 Heel padding durability 1170 non-null str \n", " 14 Outsole durability 1170 non-null str \n", " 15 Breathability 1170 non-null str \n", " 16 Width / fit 1170 non-null str \n", " 17 Toebox width 1170 non-null str \n", " 18 Stiffness 1170 non-null str \n", " 19 Torsional rigidity 1170 non-null str \n", " 20 Heel counter stiffness 1170 non-null str \n", " 21 Plate 1170 non-null str \n", " 22 Rocker 1170 non-null int64\n", " 23 Heel lab Heel brand 1170 non-null str \n", " 24 Forefoot lab Forefoot brand 1170 non-null str \n", " 25 Widths available 1170 non-null str \n", " 26 Orthotic friendly 1170 non-null int64\n", " 27 Season 1170 non-null str \n", " 28 Removable insole 1170 non-null int64\n", " 29 Ranking 1170 non-null str \n", " 30 Popularity 1170 non-null str \n", " 31 Gender 10 non-null str \n", " 32 Terrain 16 non-null str \n", "dtypes: int64(4), str(29)\n", "memory usage: 301.8 KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 3, "id": "c0b39803", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Brand (32 unique)\n", "\n", "[ 'Brooks', 'Adidas', 'Skechers', 'Salomon',\n", " 'Nike', 'NOBULL', 'Hoka', 'HOKA',\n", " 'Topo', 'Diadora', 'Saucony', 'Under Armour',\n", " 'On', 'on', 'On ', 'PUMA',\n", " 'Puma', 'NIke', 'ASICS', 'Altra',\n", " 'Reebok', 'New Balance', 'new Balance', 'Mizuno',\n", " 'Nike ', 'Jordan', 'Inov8', 'SAlomon',\n", " 'Xero', 'APL', 'Allbirds', 'Merrell']\n", "Length: 32, dtype: str\n", "\n", "Pace (5 unique)\n", "\n", "['Daily runningTempo', 'Daily running', 'Tempo',\n", " 'CompetitionTempo', 'Competition']\n", "Length: 5, dtype: str\n", "\n", "Arch support (3 unique)\n", "\n", "['Neutral', 'Motion control', 'Stability']\n", "Length: 3, dtype: str\n", "\n", "Lightweight (2 unique)\n", "[1 0]\n", "\n", "Strike pattern (5 unique)\n", "\n", "['HeelMid/forefoot', 'Mid/forefoot', 'Heel', '-', 'Heel Mid/forefoot']\n", "Length: 5, dtype: str\n", "\n", "Size (6 unique)\n", "\n", "[ 'True to size', 'Slightly small', 'Half size small', 'Slightly large',\n", " '-', 'Half size large']\n", "Length: 6, dtype: str\n", "\n", "Midsole softness (4 unique)\n", "\n", "['Balanced', 'Soft', 'Firm', '-']\n", "Length: 4, dtype: str\n", "\n", "Toebox durability (4 unique)\n", "\n", "['-', 'Good', 'Decent', 'Bad']\n", "Length: 4, dtype: str\n", "\n", "Heel padding durability (4 unique)\n", "\n", "['-', 'Good', 'Decent', 'Bad']\n", "Length: 4, dtype: str\n", "\n", "Outsole durability (4 unique)\n", "\n", "['-', 'Good', 'Decent', 'Bad']\n", "Length: 4, dtype: str\n", "\n", "Breathability (4 unique)\n", "\n", "['-', 'Breathable', 'Warm', 'Moderate']\n", "Length: 4, dtype: str\n", "\n", "Width / fit (3 unique)\n", "\n", "['Narrow', 'Medium', 'Wide']\n", "Length: 3, dtype: str\n", "\n", "Toebox width (4 unique)\n", "\n", "['-', 'Medium', 'Wide', 'Narrow']\n", "Length: 4, dtype: str\n", "\n", "Stiffness (4 unique)\n", "\n", "['Stiff', 'Moderate', 'Flexible', '-']\n", "Length: 4, dtype: str\n", "\n", "Torsional rigidity (4 unique)\n", "\n", "['Stiff', 'Moderate', 'Flexible', '-']\n", "Length: 4, dtype: str\n", "\n", "Heel counter stiffness (4 unique)\n", "\n", "['Flexible', 'Moderate', 'Stiff', '-']\n", "Length: 4, dtype: str\n", "\n", "Plate (3 unique)\n", "\n", "['0', 'Carbon plate', 'Carbon plateRock plate']\n", "Length: 3, dtype: str\n", "\n", "Rocker (2 unique)\n", "[0 1]\n", "\n", "Widths available (11 unique)\n", "\n", "[ 'NormalWide', 'Normal',\n", " 'NarrowNormalWideX-Wide', 'NormalX-Wide',\n", " 'NarrowNormalWide', 'NormalWideX-Wide',\n", " 'Narrow Normal Wide X-Wide', 'NarrowNormal',\n", " 'Normal Wide', 'NarrowNormalX-Wide',\n", " 'Normal Wide X-Wide']\n", "Length: 11, dtype: str\n", "\n", "Orthotic friendly (2 unique)\n", "[1 0]\n", "\n", "Season (4 unique)\n", "\n", "['-', 'SummerAll seasons', 'All seasons', 'Winter']\n", "Length: 4, dtype: str\n", "\n", "Removable insole (2 unique)\n", "[1 0]\n" ] } ], "source": [ "observed_col = [\n", " 'Brand',\n", " 'Pace',\n", " 'Arch support',\n", " 'Lightweight',\n", " 'Strike pattern',\n", " 'Size',\n", " 'Midsole softness',\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", " 'Plate',\n", " 'Rocker',\n", " 'Widths available',\n", " 'Orthotic friendly',\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": "code", "execution_count": 4, "id": "bbabcc2e", "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", "
BrandNameAudience scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Heel lab Heel brandForefoot lab Forefoot brandWidths availableOrthotic friendlySeasonRemovable insoleRankingPopularityGenderTerrain
\n", "

0 rows × 33 columns

\n", "
" ], "text/plain": [ "Empty DataFrame\n", "Columns: [Brand, Name, Audience score, Price, Pace, Arch support, Weight lab Weight brand, Lightweight, Drop lab Drop brand, Strike pattern, Size, Midsole softness, Toebox durability, Heel padding durability, Outsole durability, Breathability, Width / fit, Toebox width, Stiffness, Torsional rigidity, Heel counter stiffness, Plate, Rocker, Heel lab Heel brand, Forefoot lab Forefoot brand, Widths available, Orthotic friendly, Season, Removable insole, Ranking, Popularity, Gender, Terrain]\n", "Index: []\n", "\n", "[0 rows x 33 columns]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# check row dari filter masih kemasukan apa ngga\n", "df[df[\"Pace\"]== \"Select\"]" ] }, { "cell_type": "markdown", "id": "89492cc7", "metadata": {}, "source": [ "# Cleaning Brand" ] }, { "cell_type": "code", "execution_count": 6, "id": "23002f3b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Brand (24 uniques): \n", " ['Adidas', 'Allbirds', 'Altra', 'Apl', 'Asics', 'Brooks', 'Diadora', 'Hoka', 'Inov8', 'Jordan', 'Merrell', 'Mizuno', 'New Balance', 'Nike', 'Nobull', 'On', 'Puma', 'Reebok', 'Salomon', 'Saucony', 'Skechers', 'Topo', 'Under Armour', 'Xero']\n" ] }, { "data": { "text/plain": [ "Brand\n", "Asics 190\n", "Adidas 157\n", "Nike 148\n", "Brooks 130\n", "Saucony 83\n", "New Balance 82\n", "Hoka 67\n", "Mizuno 57\n", "On 52\n", "Altra 50\n", "Puma 42\n", "Under Armour 26\n", "Reebok 18\n", "Skechers 16\n", "Salomon 10\n", "Allbirds 9\n", "Nobull 7\n", "Xero 7\n", "Diadora 6\n", "Topo 5\n", "Inov8 4\n", "Merrell 2\n", "Jordan 1\n", "Apl 1\n", "Name: count, dtype: int64" ] }, "execution_count": 6, "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().head(25)" ] }, { "cell_type": "markdown", "id": "69438526", "metadata": {}, "source": [ "wow beda (cooked)" ] }, { "cell_type": "code", "execution_count": 7, "id": "402ada5a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total sepatu (rows): 1170\n" ] } ], "source": [ "total_rows = len(df)\n", "print(\"Total sepatu (rows):\", total_rows)" ] }, { "cell_type": "code", "execution_count": 8, "id": "62f507b4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Jumlah sepatu dari seluruh brand: 1170\n", "Jumlah brand unik: 24\n" ] } ], "source": [ "brand_counts = df[\"Brand\"].value_counts()\n", "print(\"Jumlah sepatu dari seluruh brand:\", brand_counts.sum())\n", "print(\"Jumlah brand unik:\", brand_counts.shape[0])\n" ] }, { "cell_type": "markdown", "id": "d7df55d3", "metadata": {}, "source": [ "terlihat sudah sama, lalu salahnya dimana? stay tuned" ] }, { "cell_type": "code", "execution_count": 9, "id": "392e4487", "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", "
BrandNameAudience scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Heel lab Heel brandForefoot lab Forefoot brandWidths availableOrthotic friendlySeasonRemovable insoleRankingPopularityGenderTerrain
839JordanReact Havoc83\\n Good!$130Daily runningNeutral9.5 oz / 268g 10.8 oz / 306g010.2 mm 9.0 mmHeel...32.3 mm 28.0 mm22.1 mm 19.0 mmNormal0-0#258 Bottom 29%#339 Bottom 7%NaNNaN
\n", "

1 rows × 33 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "839 Jordan React Havoc 83\\n Good! $130 Daily running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "839 9.5 oz / 268g 10.8 oz / 306g 0 10.2 mm 9.0 mm \n", "\n", " Strike pattern ... Heel lab Heel brand Forefoot lab Forefoot brand \\\n", "839 Heel ... 32.3 mm 28.0 mm 22.1 mm 19.0 mm \n", "\n", " Widths available Orthotic friendly Season Removable insole \\\n", "839 Normal 0 - 0 \n", "\n", " Ranking Popularity Gender Terrain \n", "839 #258 Bottom 29% #339 Bottom 7% NaN NaN \n", "\n", "[1 rows x 33 columns]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df[\"Brand\"]== \"Jordan\"]" ] }, { "cell_type": "markdown", "id": "b45c770b", "metadata": {}, "source": [ "jujur bingung dan sudah ingin crash out" ] }, { "cell_type": "code", "execution_count": 10, "id": "8fb7fb1d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Asics : 190\n", "Adidas : 157\n", "Nike : 148\n", "Brooks : 130\n", "Saucony : 83\n", "New Balance : 82\n", "Hoka : 67\n", "Mizuno : 57\n", "On : 52\n", "Altra : 50\n", "Puma : 42\n", "Under Armour : 26\n", "Reebok : 18\n", "Skechers : 16\n", "Salomon : 10\n", "Allbirds : 9\n", "Nobull : 7\n", "Xero : 7\n", "Diadora : 6\n", "Topo : 5\n", "Inov8 : 4\n", "Merrell : 2\n", "Jordan : 1\n", "Apl : 1\n" ] } ], "source": [ "brands = df[\"Brand\"].value_counts()\n", "\n", "for brand, count in brands.items():\n", " print(f\"{brand:<15} : {count}\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "fc1ea3e3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TOTAL sepatu (sum of brand counts): 1170\n" ] } ], "source": [ "print(\"TOTAL sepatu (sum of brand counts):\", brand_counts.sum())" ] }, { "cell_type": "markdown", "id": "4f4e70d6", "metadata": {}, "source": [ "kocak ternyata sudah benar" ] }, { "cell_type": "markdown", "id": "94e4aaaa", "metadata": {}, "source": [ "### Asumsi : \n", "Ada 24 unique brand dengan 1195 total sepatu. belum ada observasi lanjutan sih" ] }, { "cell_type": "markdown", "id": "ab3a7e31", "metadata": {}, "source": [ "# Cleaning Pace" ] }, { "cell_type": "code", "execution_count": 13, "id": "27408c18", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Pace (5 uniques): \n", " ['Competition', 'Competitiontempo', 'Daily Running', 'Daily Runningtempo', 'Tempo']\n" ] }, { "data": { "text/plain": [ "Pace\n", "Daily Running 813\n", "Daily Runningtempo 125\n", "Competition 88\n", "Tempo 75\n", "Competitiontempo 69\n", "Name: count, dtype: int64" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Pace\"] = (\n", " df[\"Pace\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "pace_uniques = df[\"Pace\"].dropna().unique()\n", "# pace_uniques.sort()\n", "pace_uniques = sorted(pace_uniques)\n", "print(f\"Pace ({len(pace_uniques)} uniques): \\n\",pace_uniques)\n", "\n", "df[\"Pace\"].value_counts().head(20)" ] }, { "cell_type": "markdown", "id": "4001f1bb", "metadata": {}, "source": [ "### Analisis Pace\n", "\n", "A. Lari Daily Running \n", "Tujuan: lari harian, easy run, long run \n", "Karakter: cushioning empuk, stabil, tahan lama \n", "Kelebihan: nyaman & aman untuk jarak jauh \n", "Kekurangan: berat, kurang responsif untuk ngebut \n", "\n", "B. Tempo \n", "Tujuan: tempo run, interval, latihan kecepatan \n", "Karakter: lebih ringan, responsif, midsole lebih firm \n", "Kelebihan: enak buat pace cepat tanpa lomba \n", "Kekurangan: kurang nyaman untuk lari santai jauh \n", "\n", "C. Competition \n", "Tujuan: race day, time trial \n", "Karakter: sangat ringan, agresif, sering pakai plate \n", "Kelebihan: paling cepat & efisien \n", "Kekurangan: durability rendah, tidak cocok dipakai sering" ] }, { "cell_type": "markdown", "id": "4879a798", "metadata": {}, "source": [ "### Cleaning Code" ] }, { "cell_type": "code", "execution_count": 14, "id": "3595b5fb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UNMAPPED Pace values:\n", " Series([], Name: count, dtype: int64)\n" ] } ], "source": [ "# mapping si nilai kegabung itu\n", "\n", "pace_map = {\n", " \"Competitiontempo\": \"Competition|Tempo\",\n", " \"Daily Runningtempo\": \"Daily Running|Tempo\",\n", " \"Competition\": \"Competition\",\n", " \"Daily Running\": \"Daily Running\",\n", " \"Tempo\": \"Tempo\",\n", "}\n", "\n", "df[\"Pace_norm\"] = df[\"Pace\"].map(pace_map)\n", "\n", "unmapped = df[df[\"Pace_norm\"].isna()][\"Pace\"].value_counts()\n", "print(\"UNMAPPED Pace values:\\n\", unmapped)\n", "assert df[\"Pace_norm\"].notna().all()" ] }, { "cell_type": "code", "execution_count": 15, "id": "855d02a9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Pace - norm : (5) uniques\n", " \n", "['Daily Running|Tempo', 'Daily Running', 'Tempo',\n", " 'Competition|Tempo', 'Competition']\n", "Length: 5, dtype: str\n" ] }, { "data": { "text/plain": [ "Pace_norm\n", "Daily Running 813\n", "Daily Running|Tempo 125\n", "Competition 88\n", "Tempo 75\n", "Competition|Tempo 69\n", "Name: count, dtype: int64" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pace_norms_unique = df[\"Pace_norm\"].dropna().unique()\n", "print(f\"Pace - norm : ({len(pace_norms_unique)}) uniques\\n\", pace_norms_unique)\n", "\n", "\n", "df[\"Pace_norm\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 16, "id": "22a5e00c", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Widths availableOrthotic friendlySeasonRemovable insoleRankingPopularityGenderTerrainPace_normPace_lists
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelMid/forefoot...NormalWide1-1#301 Top 47%#352 Bottom 45%NaNNaNDaily Running|Tempo[Daily Running, Tempo]
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/forefoot...Normal1SummerAll seasons1#72 Top 20%#255 Bottom 30%NaNNaNDaily Running[Daily Running]
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelMid/forefoot...Normal1All seasons1#104 Top 17%#368 Bottom 42%NaNNaNDaily Running[Daily Running]
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...Normal1All seasons1#126 Top 20%#541 Bottom 16%NaNNaNDaily Running[Daily Running]
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelMid/forefoot...Normal1All seasons1#116 Top 32%#339 Bottom 7%NaNNaNDaily Running[Daily Running]
\n", "

5 rows × 35 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Widths available Orthotic friendly \\\n", "0 HeelMid/forefoot ... NormalWide 1 \n", "1 Mid/forefoot ... Normal 1 \n", "2 HeelMid/forefoot ... Normal 1 \n", "3 Heel ... Normal 1 \n", "4 HeelMid/forefoot ... Normal 1 \n", "\n", " Season Removable insole Ranking Popularity Gender \\\n", "0 - 1 #301 Top 47% #352 Bottom 45% NaN \n", "1 SummerAll seasons 1 #72 Top 20% #255 Bottom 30% NaN \n", "2 All seasons 1 #104 Top 17% #368 Bottom 42% NaN \n", "3 All seasons 1 #126 Top 20% #541 Bottom 16% NaN \n", "4 All seasons 1 #116 Top 32% #339 Bottom 7% NaN \n", "\n", " Terrain Pace_norm Pace_lists \n", "0 NaN Daily Running|Tempo [Daily Running, Tempo] \n", "1 NaN Daily Running [Daily Running] \n", "2 NaN Daily Running [Daily Running] \n", "3 NaN Daily Running [Daily Running] \n", "4 NaN Daily Running [Daily Running] \n", "\n", "[5 rows x 35 columns]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Pace_lists\"] = df[\"Pace_norm\"].str.split(\"|\")\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 17, "id": "16bae2d7", "metadata": {}, "outputs": [], "source": [ "# df = df.drop(labels=\"Pace_list\", axis=1)" ] }, { "cell_type": "code", "execution_count": 18, "id": "25796d54", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Widths availableOrthotic friendlySeasonRemovable insoleRankingPopularityGenderTerrainPace_normPace_lists
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelMid/forefoot...NormalWide1-1#301 Top 47%#352 Bottom 45%NaNNaNDaily Running|Tempo[Daily Running, Tempo]
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/forefoot...Normal1SummerAll seasons1#72 Top 20%#255 Bottom 30%NaNNaNDaily Running[Daily Running]
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelMid/forefoot...Normal1All seasons1#104 Top 17%#368 Bottom 42%NaNNaNDaily Running[Daily Running]
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...Normal1All seasons1#126 Top 20%#541 Bottom 16%NaNNaNDaily Running[Daily Running]
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelMid/forefoot...Normal1All seasons1#116 Top 32%#339 Bottom 7%NaNNaNDaily Running[Daily Running]
\n", "

5 rows × 35 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Widths available Orthotic friendly \\\n", "0 HeelMid/forefoot ... NormalWide 1 \n", "1 Mid/forefoot ... Normal 1 \n", "2 HeelMid/forefoot ... Normal 1 \n", "3 Heel ... Normal 1 \n", "4 HeelMid/forefoot ... Normal 1 \n", "\n", " Season Removable insole Ranking Popularity Gender \\\n", "0 - 1 #301 Top 47% #352 Bottom 45% NaN \n", "1 SummerAll seasons 1 #72 Top 20% #255 Bottom 30% NaN \n", "2 All seasons 1 #104 Top 17% #368 Bottom 42% NaN \n", "3 All seasons 1 #126 Top 20% #541 Bottom 16% NaN \n", "4 All seasons 1 #116 Top 32% #339 Bottom 7% NaN \n", "\n", " Terrain Pace_norm Pace_lists \n", "0 NaN Daily Running|Tempo [Daily Running, Tempo] \n", "1 NaN Daily Running [Daily Running] \n", "2 NaN Daily Running [Daily Running] \n", "3 NaN Daily Running [Daily Running] \n", "4 NaN Daily Running [Daily Running] \n", "\n", "[5 rows x 35 columns]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 19, "id": "97aed74a", "metadata": {}, "outputs": [], "source": [ "# jujur ini vibe ah coding\n", "pace_exploded = df[\"Pace_lists\"].explode()\n", "\n", "pace_ohe = (\n", " pd.crosstab(pace_exploded.index, pace_exploded)\n", " .reindex(df.index, fill_value=0) # jaga urutan index sama df\n", ")\n", "\n", "# rename kolom biar konsisten untuk ML pipeline\n", "pace_ohe = pace_ohe.rename(columns={\n", " \"Competition\": \"pace_competition\",\n", " \"Daily Running\": \"pace_daily_running\",\n", " \"Tempo\": \"pace_tempo\"\n", "})\n", "\n", "# gabung ke df\n", "df = pd.concat([df, pace_ohe], axis=1)\n" ] }, { "cell_type": "code", "execution_count": 20, "id": "7ce9dc57", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Removable insoleRankingPopularityGenderTerrainPace_normPace_listspace_competitionpace_daily_runningpace_tempo
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelMid/forefoot...1#301 Top 47%#352 Bottom 45%NaNNaNDaily Running|Tempo[Daily Running, Tempo]011
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/forefoot...1#72 Top 20%#255 Bottom 30%NaNNaNDaily Running[Daily Running]010
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelMid/forefoot...1#104 Top 17%#368 Bottom 42%NaNNaNDaily Running[Daily Running]010
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...1#126 Top 20%#541 Bottom 16%NaNNaNDaily Running[Daily Running]010
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelMid/forefoot...1#116 Top 32%#339 Bottom 7%NaNNaNDaily Running[Daily Running]010
\n", "

5 rows × 38 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Removable insole Ranking Popularity \\\n", "0 HeelMid/forefoot ... 1 #301 Top 47% #352 Bottom 45% \n", "1 Mid/forefoot ... 1 #72 Top 20% #255 Bottom 30% \n", "2 HeelMid/forefoot ... 1 #104 Top 17% #368 Bottom 42% \n", "3 Heel ... 1 #126 Top 20% #541 Bottom 16% \n", "4 HeelMid/forefoot ... 1 #116 Top 32% #339 Bottom 7% \n", "\n", " Gender Terrain Pace_norm Pace_lists \\\n", "0 NaN NaN Daily Running|Tempo [Daily Running, Tempo] \n", "1 NaN NaN Daily Running [Daily Running] \n", "2 NaN NaN Daily Running [Daily Running] \n", "3 NaN NaN Daily Running [Daily Running] \n", "4 NaN NaN Daily Running [Daily Running] \n", "\n", " pace_competition pace_daily_running pace_tempo \n", "0 0 1 1 \n", "1 0 1 0 \n", "2 0 1 0 \n", "3 0 1 0 \n", "4 0 1 0 \n", "\n", "[5 rows x 38 columns]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 21, "id": "53f241a3", "metadata": {}, "outputs": [], "source": [ "# make sure value-nya bener 0/1\n", "for c in [\"pace_competition\", \"pace_daily_running\", \"pace_tempo\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n" ] }, { "cell_type": "code", "execution_count": 22, "id": "7e51526a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Pace Pace_norm pace_competition pace_tempo \\\n", "24 Competitiontempo Competition|Tempo 1 1 \n", "32 Competitiontempo Competition|Tempo 1 1 \n", "33 Competitiontempo Competition|Tempo 1 1 \n", "34 Competitiontempo Competition|Tempo 1 1 \n", "38 Competitiontempo Competition|Tempo 1 1 \n", "\n", " pace_daily_running \n", "24 0 \n", "32 0 \n", "33 0 \n", "34 0 \n", "38 0 \n", " Pace Pace_norm pace_daily_running pace_tempo \\\n", "0 Daily Runningtempo Daily Running|Tempo 1 1 \n", "7 Daily Runningtempo Daily Running|Tempo 1 1 \n", "35 Daily Runningtempo Daily Running|Tempo 1 1 \n", "36 Daily Runningtempo Daily Running|Tempo 1 1 \n", "37 Daily Runningtempo Daily Running|Tempo 1 1 \n", "\n", " pace_competition \n", "0 0 \n", "7 0 \n", "35 0 \n", "36 0 \n", "37 0 \n" ] } ], "source": [ "print(df[df[\"Pace\"]==\"Competitiontempo\"][[\"Pace\",\"Pace_norm\",\"pace_competition\",\"pace_tempo\",\"pace_daily_running\"]].head())\n", "print(df[df[\"Pace\"]==\"Daily Runningtempo\"][[\"Pace\",\"Pace_norm\",\"pace_daily_running\",\"pace_tempo\",\"pace_competition\"]].head())" ] }, { "cell_type": "code", "execution_count": 23, "id": "67cbfef0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "competition sum: 157\n", "daily sum: 938\n", "tempo sum: 269\n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"competition sum:\", int(df[\"pace_competition\"].sum()))\n", "print(\"daily sum:\", int(df[\"pace_daily_running\"].sum()))\n", "print(\"tempo sum:\", int(df[\"pace_tempo\"].sum()))" ] }, { "cell_type": "markdown", "id": "bc4bd121", "metadata": {}, "source": [ "### Asumsi : \n", "ada 2 jenis kombinasi : competion tempo sama daily tempo, setelah dipisah jadi dapet gini\n", "Rows: 1195\n", "competition sum: 157\n", "daily sum: 963\n", "tempo sum: 272" ] }, { "cell_type": "markdown", "id": "9cc22c3c", "metadata": {}, "source": [ "# Cleaning Arch Support" ] }, { "cell_type": "code", "execution_count": 25, "id": "90afbf61", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Arch (3 uniques): \n", " ['Motion Control', 'Neutral', 'Stability']\n" ] }, { "data": { "text/plain": [ "Arch support\n", "Neutral 999\n", "Stability 170\n", "Motion Control 1\n", "Name: count, dtype: int64" ] }, "execution_count": 25, "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": "markdown", "id": "e9c82b15", "metadata": {}, "source": [ "Neutral\n", "Untuk siapa: pelari dengan gait normal / netral\n", "Ciri: tidak ada koreksi khusus pada midsole\n", "Kelebihan: fleksibel, natural, nyaman untuk mayoritas pelari\n", "Catatan: ini adalah default dan paling umum di pasaran\n", "\n", "Stability\n", "Untuk siapa: pelari dengan overpronation ringan–sedang\n", "Ciri: ada struktur tambahan (medial support, geometry khusus)\n", "Kelebihan: membantu menjaga kaki tetap stabil tanpa terlalu kaku\n", "Catatan: masih nyaman untuk daily running\n", "\n", "Motion Control\n", "Untuk siapa: overpronation berat\n", "Ciri: sangat kaku dan korektif\n", "Kelebihan: kontrol maksimal\n", "Kekurangan: berat, kurang nyaman, sangat niche\n", "Catatan: di market modern, kategori ini hampir punah" ] }, { "cell_type": "markdown", "id": "33f99ae3", "metadata": {}, "source": [ "bentar ya saya mengantuk" ] }, { "cell_type": "markdown", "id": "cee5e7e6", "metadata": {}, "source": [ "------------------------- day 2 ------------------------------------" ] }, { "cell_type": "code", "execution_count": 26, "id": "e4a2846c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Arch_grouped\n", "Neutral 999\n", "Stability 171\n", "Name: count, dtype: int64\n" ] } ], "source": [ "arch_map = {\n", " \"Neutral\": \"Neutral\",\n", " \"Stability\": \"Stability\",\n", " \"Motion Control\": \"Stability\" # cuma ada 1 makanya digabung ke stability, mereka sama sama buat low arch\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": 27, "id": "6026d0e4", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...GenderTerrainPace_normPace_listspace_competitionpace_daily_runningpace_tempoArch_groupedarch_neutralarch_stability
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelMid/forefoot...NaNNaNDaily Running|Tempo[Daily Running, Tempo]011Neutral10
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/forefoot...NaNNaNDaily Running[Daily Running]010Neutral10
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelMid/forefoot...NaNNaNDaily Running[Daily Running]010Neutral10
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...NaNNaNDaily Running[Daily Running]010Neutral10
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelMid/forefoot...NaNNaNDaily Running[Daily Running]010Neutral10
\n", "

5 rows × 41 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Gender Terrain Pace_norm \\\n", "0 HeelMid/forefoot ... NaN NaN Daily Running|Tempo \n", "1 Mid/forefoot ... NaN NaN Daily Running \n", "2 HeelMid/forefoot ... NaN NaN Daily Running \n", "3 Heel ... NaN NaN Daily Running \n", "4 HeelMid/forefoot ... NaN NaN Daily Running \n", "\n", " Pace_lists pace_competition pace_daily_running pace_tempo \\\n", "0 [Daily Running, Tempo] 0 1 1 \n", "1 [Daily Running] 0 1 0 \n", "2 [Daily Running] 0 1 0 \n", "3 [Daily Running] 0 1 0 \n", "4 [Daily Running] 0 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": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# vibe ah coding\n", "arch_ohe = pd.get_dummies(df[\"Arch_grouped\"], prefix=\"arch\", dtype=int)\n", "\n", "# Rename kolom biar lowercase dan konsisten (opsional, tapi rapi)\n", "arch_ohe = arch_ohe.rename(columns={\n", " \"arch_Neutral\": \"arch_neutral\",\n", " \"arch_Stability\": \"arch_stability\"\n", "})\n", "\n", "\n", "\n", "df = pd.concat([df, arch_ohe], axis=1)\n", "df.head()\n" ] }, { "cell_type": "code", "execution_count": 28, "id": "cc40c12f", "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": 29, "id": "f7996392", "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 Motion Control 0 1\n", "7 Neutral 1 0\n", "8 Neutral 1 0\n", "9 Neutral 1 0\n", "\n", "Total Neutral : 999\n", "Total Stability : 171\n" ] } ], "source": [ "# Pastikan setiap sepatu punya salah satu (tidak bisa 0 dua-duanya atau 1 dua-duanya, karena ini single choice)\n", "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": "d85aa91e", "metadata": {}, "source": [ "harusnya sebenernya motion diubah ke stability tuh pas preprocessing aja" ] }, { "cell_type": "markdown", "id": "291b7806", "metadata": {}, "source": [ "# Cleaning Strike" ] }, { "cell_type": "code", "execution_count": 31, "id": "462dfdeb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Strike pattern (5 uniques): \n", " ['-', 'Heel', 'Heel Mid/Forefoot', 'Heelmid/Forefoot', 'Mid/Forefoot']\n" ] }, { "data": { "text/plain": [ "Strike pattern\n", "Heelmid/Forefoot 539\n", "Mid/Forefoot 339\n", "Heel 290\n", "- 1\n", "Heel Mid/Forefoot 1\n", "Name: count, dtype: int64" ] }, "execution_count": 31, "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": 32, "id": "06e495eb", "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", "
BrandNameAudience scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...PopularityGenderTerrainPace_normPace_listspace_competitionpace_daily_runningpace_tempoarch_neutralarch_stability
301NikeFlex Experience Run 1079\\n Good!$65Daily RunningNeutral7.1 oz / 201g 8 oz / 227g110.4 mm-...#523 Bottom 18%NaNNaNDaily Running[Daily Running]01010
\n", "

1 rows × 40 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace \\\n", "301 Nike Flex Experience Run 10 79\\n Good! $65 Daily Running \n", "\n", " Arch support Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "301 Neutral 7.1 oz / 201g 8 oz / 227g 1 10.4 mm \n", "\n", " Strike pattern ... Popularity Gender Terrain Pace_norm \\\n", "301 - ... #523 Bottom 18% NaN NaN Daily Running \n", "\n", " Pace_lists pace_competition pace_daily_running pace_tempo \\\n", "301 [Daily Running] 0 1 0 \n", "\n", " arch_neutral arch_stability \n", "301 1 0 \n", "\n", "[1 rows x 40 columns]" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df[\"Strike pattern\"] == \"-\"]" ] }, { "cell_type": "markdown", "id": "c09196ce", "metadata": {}, "source": [ "seharusnya ga ada issue kalo kita hapus si FER 10 soalnya dia udah punya FER 12" ] }, { "cell_type": "code", "execution_count": 33, "id": "9c31c1ce", "metadata": {}, "outputs": [], "source": [ "# df[df[\"Name\"] == \"Flex Experience Run 12\"]" ] }, { "cell_type": "code", "execution_count": 34, "id": "dc940543", "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", "
BrandNameAudience scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...PopularityGenderTerrainPace_normPace_listspace_competitionpace_daily_runningpace_tempoarch_neutralarch_stability
1090NikeVomero Plus91 Superb!$180Daily RunningNeutral10.2 oz / 289g 10.1 oz / 285g09.6 mm 10.0 mmHeel Mid/Forefoot...#7 Top 2%NaNNaNDaily Running[Daily Running]01010
\n", "

1 rows × 40 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "1090 Nike Vomero Plus 91 Superb! $180 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "1090 10.2 oz / 289g 10.1 oz / 285g 0 9.6 mm 10.0 mm \n", "\n", " Strike pattern ... Popularity Gender Terrain Pace_norm \\\n", "1090 Heel Mid/Forefoot ... #7 Top 2% NaN NaN Daily Running \n", "\n", " Pace_lists pace_competition pace_daily_running pace_tempo \\\n", "1090 [Daily Running] 0 1 0 \n", "\n", " arch_neutral arch_stability \n", "1090 1 0 \n", "\n", "[1 rows x 40 columns]" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df[\"Strike pattern\"] == \"Heel Mid/Forefoot\"]" ] }, { "cell_type": "code", "execution_count": 35, "id": "a32a50e8", "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...PopularityGenderTerrainPace_normPace_listspace_competitionpace_daily_runningpace_tempoarch_neutralarch_stability
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...#352 Bottom 45%NaNNaNDaily Running|Tempo[Daily Running, Tempo]01110
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...#368 Bottom 42%NaNNaNDaily Running[Daily Running]01010
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...#339 Bottom 7%NaNNaNDaily Running[Daily Running]01010
5Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...#339 Bottom 7%NaNNaNDaily Running[Daily Running]01010
7AdidasAdidas Adizero SL290\\n Superb!$130Daily RunningtempoNeutral8.6 oz / 245g 8.4 oz / 238g18.2 mm 9.0 mmHeelmid/Forefoot...#166 Top 46%NaNNaNDaily Running|Tempo[Daily Running, Tempo]01110
..................................................................
1154MizunoWWave Horizon 788\\n Great!$170Daily RunningStability11.6 oz / 329g 11.8 oz / 334g07.2 mm 8.0 mmHeelmid/Forefoot...#294 Bottom 19%NaNNaNDaily Running[Daily Running]01001
1155ReebokZig Dynamica 480\\n Good!$85Daily RunningNeutral12.4 oz / 352g 12.3 oz / 350g08.5 mm 9.0 mmHeelmid/Forefoot...#533 Bottom 17%NaNNaNDaily Running[Daily Running]01010
1160NikeZoom Fly 692\\n Superb!$170CompetitiontempoNeutral8.7 oz / 248g 8.6 oz / 244g19.6 mm 8.0 mmHeelmid/Forefoot...#26 Top 8%NaNNaNCompetition|Tempo[Competition, Tempo]10110
1161NikeZoom Fly 692\\n Superb!$170CompetitiontempoNeutral8.7 oz / 248g 8.6 oz / 244g19.6 mm 8.0 mmHeelmid/Forefoot...#26 Top 8%NaNNaNCompetition|Tempo[Competition, Tempo]10110
1162NikeZoom Fly 692\\n Superb!$170CompetitiontempoNeutral8.7 oz / 248g 8.6 oz / 244g19.6 mm 8.0 mmHeelmid/Forefoot...#26 Top 8%NaNNaNCompetition|Tempo[Competition, Tempo]10110
\n", "

539 rows × 40 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running \n", "5 Adidas 4DFWD 3 88\\n Great! $200 Daily Running \n", "7 Adidas Adidas Adizero SL2 90\\n Superb! $130 Daily Runningtempo \n", "... ... ... ... ... ... \n", "1154 Mizuno WWave Horizon 7 88\\n Great! $170 Daily Running \n", "1155 Reebok Zig Dynamica 4 80\\n Good! $85 Daily Running \n", "1160 Nike Zoom Fly 6 92\\n Superb! $170 Competitiontempo \n", "1161 Nike Zoom Fly 6 92\\n Superb! $170 Competitiontempo \n", "1162 Nike Zoom Fly 6 92\\n Superb! $170 Competitiontempo \n", "\n", " Arch support Weight lab Weight brand Lightweight \\\n", "0 Neutral 7.9 oz / 225g 8.1 oz / 230g 1 \n", "2 Neutral 11.9 oz / 336g 11.5 oz / 327g 0 \n", "4 Neutral 12.3 oz / 348g 12.2 oz / 345g 0 \n", "5 Neutral 12.3 oz / 348g 12.2 oz / 345g 0 \n", "7 Neutral 8.6 oz / 245g 8.4 oz / 238g 1 \n", "... ... ... ... \n", "1154 Stability 11.6 oz / 329g 11.8 oz / 334g 0 \n", "1155 Neutral 12.4 oz / 352g 12.3 oz / 350g 0 \n", "1160 Neutral 8.7 oz / 248g 8.6 oz / 244g 1 \n", "1161 Neutral 8.7 oz / 248g 8.6 oz / 244g 1 \n", "1162 Neutral 8.7 oz / 248g 8.6 oz / 244g 1 \n", "\n", " Drop lab Drop brand Strike pattern ... Popularity Gender \\\n", "0 9.4 mm 10.0 mm Heelmid/Forefoot ... #352 Bottom 45% NaN \n", "2 8.9 mm 10.0 mm Heelmid/Forefoot ... #368 Bottom 42% NaN \n", "4 9.9 mm 10.0 mm Heelmid/Forefoot ... #339 Bottom 7% NaN \n", "5 9.9 mm 10.0 mm Heelmid/Forefoot ... #339 Bottom 7% NaN \n", "7 8.2 mm 9.0 mm Heelmid/Forefoot ... #166 Top 46% NaN \n", "... ... ... ... ... ... \n", "1154 7.2 mm 8.0 mm Heelmid/Forefoot ... #294 Bottom 19% NaN \n", "1155 8.5 mm 9.0 mm Heelmid/Forefoot ... #533 Bottom 17% NaN \n", "1160 9.6 mm 8.0 mm Heelmid/Forefoot ... #26 Top 8% NaN \n", "1161 9.6 mm 8.0 mm Heelmid/Forefoot ... #26 Top 8% NaN \n", "1162 9.6 mm 8.0 mm Heelmid/Forefoot ... #26 Top 8% NaN \n", "\n", " Terrain Pace_norm Pace_lists pace_competition \\\n", "0 NaN Daily Running|Tempo [Daily Running, Tempo] 0 \n", "2 NaN Daily Running [Daily Running] 0 \n", "4 NaN Daily Running [Daily Running] 0 \n", "5 NaN Daily Running [Daily Running] 0 \n", "7 NaN Daily Running|Tempo [Daily Running, Tempo] 0 \n", "... ... ... ... ... \n", "1154 NaN Daily Running [Daily Running] 0 \n", "1155 NaN Daily Running [Daily Running] 0 \n", "1160 NaN Competition|Tempo [Competition, Tempo] 1 \n", "1161 NaN Competition|Tempo [Competition, Tempo] 1 \n", "1162 NaN Competition|Tempo [Competition, Tempo] 1 \n", "\n", " pace_daily_running pace_tempo arch_neutral arch_stability \n", "0 1 1 1 0 \n", "2 1 0 1 0 \n", "4 1 0 1 0 \n", "5 1 0 1 0 \n", "7 1 1 1 0 \n", "... ... ... ... ... \n", "1154 1 0 0 1 \n", "1155 1 0 1 0 \n", "1160 0 1 1 0 \n", "1161 0 1 1 0 \n", "1162 0 1 1 0 \n", "\n", "[539 rows x 40 columns]" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df[\"Strike pattern\"] == \"Heelmid/Forefoot\"]" ] }, { "cell_type": "markdown", "id": "0cc507c7", "metadata": {}, "source": [ "### Analisis Strike Pattern" ] }, { "attachments": { "image.png": { "image/png": "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a6lJctXatfLOO+/IpEmTNvkctLE+P3516J99/rkAcHAtXBPXRt5D1ZEA9930IN5V//TTTwKPla345x95+pln5NJLL5WxY8caebMwL/BAXze1EfQWSFSft9H1799fpk2b5li4Hq7LZfy/TZIAlbhv2KmrrrrK2Svy0Esa0I2BAwcK5+HelUT7tJlMZ4o6B3WBRHzo3JtvvBHzE/zGgET85ZFeJRx6dvYKufmmm+SjkSNL7R78s2SJ3HzzzTLqiy826Rw33HCDPP3445K/fn3c+qkpIsM++EA+jl7D+5rmmtbkrIrL74mVUwIY4BEjRsi3SRzzgAED5J577okJ4PJLLpF/qwH/ZswYmT1rVoy+qYkFCxZI795nyNivv96kJmbPni1nnHGafPX1lwnrL1uxQl599VWZPWeO4+F6hg4d6tL+36ZLYODAAXJyz57y/vvvy4wZM0ptjw+27OyzzpKRaq9m6f3e9B5HauJszz7jDBk27P0IYSP/M6g1nWNyFK86Ove6OvSJEye64icef1yeefppl64o/1IrSkcrez+///57+UdnUsnWfx588MFChrqyy8Rf34YSQD8eV0PDAHDD0gglPT3dJcxwjdMZ+//17Svf//CDnHzKKa5sc/6tXLlSvtbBQWbNmpvUzJ9//imjR4+WBvXrJ6zfrFkz+fjjj+WQgw92b15cvcoPXBMKayMKvvzqK+l6+OHy+++/u9kza84bUT0Ja0ERs+AfVNd6n3aa/KpR0YtU9wpKNy01d/58+fa772TVJugBv4OFixa5+pydyRE4DOjckCFD3G+EgXNubsV742eVcuhrNSxO6LFHjx7S54ILJBzCI09Y0srD4cmlS5c6h3ryySfLaaqshARRlrBixMsTLnrxxRddPdpnxkF71If+pRpIlAmnTX1ohMZuueUWV4fQD+GggQMHUrwBENai7/SZNmGAn35yPtphZgXdQ/mRAPeLex7UPe4xRrFfv37CveujumpLOdxbdIN7a1dBXXjgRb/R84yMDFm0cIHT16k6E/ti1CiXRueoh26de+aZrv14usGSDvpEm2D6ST106L7//U8W/vWX3KRRL/SSPlEWBELlDDqOO+44p7+cDz7O/9hjj8nfixfLtdde636DzJ6QATrMb4swLbN4+kU/GMTUzMyMNc9sjTZon/YooF/wUx+dD8qHcg8iyJgZ8286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" } }, "cell_type": "markdown", "id": "2f00986c", "metadata": {}, "source": [ "![image.png](attachment:image.png)" ] }, { "cell_type": "markdown", "id": "d9c3ed8b", "metadata": {}, "source": [ "A. Heel Strike (Pendaratan Tumit)\n", "Artinya: Pelari mendarat dengan tumit terlebih dahulu menyentuh tanah.\n", "Populasi: Sangat umum, mencakup sekitar 75-90% pelari rekreasional/pemula.\n", "Kebutuhan Sepatu: Membutuhkan bantalan (cushioning) yang tebal di bagian tumit untuk meredam benturan (impact). Biasanya memiliki High Drop (8mm - 12mm).\n", "\n", "B. Mid/Forefoot Strike (Pendaratan Tengah/Depan)\n", "Artinya: Pelari mendarat dengan bagian tengah atau depan kaki (jinjit).\n", "Populasi: Lebih umum pada pelari cepat, atlet elite, atau pelari minimalis.\n", "Kebutuhan Sepatu: Tidak butuh tumit tebal (karena tumit jarang menyentuh tanah keras). Biasanya butuh sepatu yang responsif dengan Low Drop (0mm - 6mm) agar pendaratan lebih natural.\n", "\n", "C. Heel/Mid/Forefoot (Versatile / All-Rounder)\n", "Artinya: Sepatu ini didesain fleksibel untuk mengakomodasi semua gaya lari.\n", "Teknologi: Biasanya menggunakan desain Rocker (lengkungan sol seperti kursi goyang) yang membuat transisi dari tumit ke ujung kaki menjadi mulus (smooth transition).\n", "Cocok untuk: Pelari yang gaya larinya berubah-ubah tergantung kelelahan (misal: awal lari midfoot, pas capek jadi heel strike)." ] }, { "cell_type": "markdown", "id": "cabe5a60", "metadata": {}, "source": [ "### Cleaning code" ] }, { "cell_type": "code", "execution_count": 36, "id": "bdbee9f5", "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 Mid/Forefoot\": \"Heel|Mid|Forefoot\",\n", " \"-\": \"-\",\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": 37, "id": "6ce0b921", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Strike - norm : (4) uniques\n", " \n", "['Heel|Mid|Forefoot', 'Mid|Forefoot', 'Heel', '-']\n", "Length: 4, dtype: str\n" ] }, { "data": { "text/plain": [ "Strike_norm\n", "Heel|Mid|Forefoot 540\n", "Mid|Forefoot 339\n", "Heel 290\n", "- 1\n", "Name: count, dtype: int64" ] }, "execution_count": 37, "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": 38, "id": "e31dde3b", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...TerrainPace_normPace_listspace_competitionpace_daily_runningpace_tempoarch_neutralarch_stabilityStrike_normStrike_lists
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...NaNDaily Running|Tempo[Daily Running, Tempo]01110Heel|Mid|Forefoot[Heel, Mid, Forefoot]
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...NaNDaily Running[Daily Running]01010Mid|Forefoot[Mid, Forefoot]
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...NaNDaily Running[Daily Running]01010Heel|Mid|Forefoot[Heel, Mid, Forefoot]
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...NaNDaily Running[Daily Running]01010Heel[Heel]
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...NaNDaily Running[Daily Running]01010Heel|Mid|Forefoot[Heel, Mid, Forefoot]
\n", "

5 rows × 42 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Terrain Pace_norm Pace_lists \\\n", "0 Heelmid/Forefoot ... NaN Daily Running|Tempo [Daily Running, Tempo] \n", "1 Mid/Forefoot ... NaN Daily Running [Daily Running] \n", "2 Heelmid/Forefoot ... NaN Daily Running [Daily Running] \n", "3 Heel ... NaN Daily Running [Daily Running] \n", "4 Heelmid/Forefoot ... NaN Daily Running [Daily Running] \n", "\n", " pace_competition pace_daily_running pace_tempo arch_neutral arch_stability \\\n", "0 0 1 1 1 0 \n", "1 0 1 0 1 0 \n", "2 0 1 0 1 0 \n", "3 0 1 0 1 0 \n", "4 0 1 0 1 0 \n", "\n", " Strike_norm Strike_lists \n", "0 Heel|Mid|Forefoot [Heel, Mid, Forefoot] \n", "1 Mid|Forefoot [Mid, Forefoot] \n", "2 Heel|Mid|Forefoot [Heel, Mid, Forefoot] \n", "3 Heel [Heel] \n", "4 Heel|Mid|Forefoot [Heel, Mid, Forefoot] \n", "\n", "[5 rows x 42 columns]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Strike_lists\"] = df[\"Strike_norm\"].str.split(\"|\")\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 39, "id": "752457fa", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'\\n# jujur ini vibe ah coding\\npace_exploded = df[\"Pace_lists\"].explode()\\n\\npace_ohe = (\\n pd.crosstab(pace_exploded.index, pace_exploded)\\n .reindex(df.index, fill_value=0) # jaga urutan index sama df\\n)\\n\\n# rename kolom biar konsisten untuk ML pipeline\\npace_ohe = pace_ohe.rename(columns={\\n \"Competition\": \"pace_competition\",\\n \"Daily Running\": \"pace_daily_running\",\\n \"Tempo\": \"pace_tempo\"\\n})\\n\\n# gabung ke df\\ndf = pd.concat([df, pace_ohe], axis=1)\\n# make sure value-nya bener 0/1\\nfor c in [\"pace_competition\", \"pace_daily_running\", \"pace_tempo\"]:\\n assert set(df[c].unique()).issubset({0, 1})\\nprint(df[df[\"Pace\"]==\"Competitiontempo\"][[\"Pace\",\"Pace_norm\",\"pace_competition\",\"pace_tempo\",\"pace_daily_running\"]].head())\\nprint(df[df[\"Pace\"]==\"Daily Runningtempo\"][[\"Pace\",\"Pace_norm\",\"pace_daily_running\",\"pace_tempo\",\"pace_competition\"]].head())\\nprint(\"Rows:\", len(df))\\nprint(\"competition sum:\", int(df[\"pace_competition\"].sum()))\\nprint(\"daily sum:\", int(df[\"pace_daily_running\"].sum()))\\nprint(\"tempo sum:\", int(df[\"pace_tempo\"].sum()))\\n'" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'''\n", "# jujur ini vibe ah coding\n", "pace_exploded = df[\"Pace_lists\"].explode()\n", "\n", "pace_ohe = (\n", " pd.crosstab(pace_exploded.index, pace_exploded)\n", " .reindex(df.index, fill_value=0) # jaga urutan index sama df\n", ")\n", "\n", "# rename kolom biar konsisten untuk ML pipeline\n", "pace_ohe = pace_ohe.rename(columns={\n", " \"Competition\": \"pace_competition\",\n", " \"Daily Running\": \"pace_daily_running\",\n", " \"Tempo\": \"pace_tempo\"\n", "})\n", "\n", "# gabung ke df\n", "df = pd.concat([df, pace_ohe], axis=1)\n", "# make sure value-nya bener 0/1\n", "for c in [\"pace_competition\", \"pace_daily_running\", \"pace_tempo\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "print(df[df[\"Pace\"]==\"Competitiontempo\"][[\"Pace\",\"Pace_norm\",\"pace_competition\",\"pace_tempo\",\"pace_daily_running\"]].head())\n", "print(df[df[\"Pace\"]==\"Daily Runningtempo\"][[\"Pace\",\"Pace_norm\",\"pace_daily_running\",\"pace_tempo\",\"pace_competition\"]].head())\n", "print(\"Rows:\", len(df))\n", "print(\"competition sum:\", int(df[\"pace_competition\"].sum()))\n", "print(\"daily sum:\", int(df[\"pace_daily_running\"].sum()))\n", "print(\"tempo sum:\", int(df[\"pace_tempo\"].sum()))\n", "'''" ] }, { "cell_type": "code", "execution_count": 40, "id": "3f553259", "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": 41, "id": "89c7f686", "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": 42, "id": "536b9e6c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "Heels sum: 830\n", "Mid sum: 879\n", "Forefoot sum: 879\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": 43, "id": "0ef394bc", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...pace_daily_runningpace_tempoarch_neutralarch_stabilityStrike_normStrike_lists-strike_forefootstrike_heelstrike_mid
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...1110Heel|Mid|Forefoot[Heel, Mid, Forefoot]0111
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...1010Mid|Forefoot[Mid, Forefoot]0101
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...1010Heel|Mid|Forefoot[Heel, Mid, Forefoot]0111
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...1010Heel[Heel]0010
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...1010Heel|Mid|Forefoot[Heel, Mid, Forefoot]0111
\n", "

5 rows × 46 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... pace_daily_running pace_tempo arch_neutral \\\n", "0 Heelmid/Forefoot ... 1 1 1 \n", "1 Mid/Forefoot ... 1 0 1 \n", "2 Heelmid/Forefoot ... 1 0 1 \n", "3 Heel ... 1 0 1 \n", "4 Heelmid/Forefoot ... 1 0 1 \n", "\n", " arch_stability Strike_norm Strike_lists - strike_forefoot \\\n", "0 0 Heel|Mid|Forefoot [Heel, Mid, Forefoot] 0 1 \n", "1 0 Mid|Forefoot [Mid, Forefoot] 0 1 \n", "2 0 Heel|Mid|Forefoot [Heel, Mid, Forefoot] 0 1 \n", "3 0 Heel [Heel] 0 0 \n", "4 0 Heel|Mid|Forefoot [Heel, Mid, Forefoot] 0 1 \n", "\n", " strike_heel strike_mid \n", "0 1 1 \n", "1 0 1 \n", "2 1 1 \n", "3 1 0 \n", "4 1 1 \n", "\n", "[5 rows x 46 columns]" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "markdown", "id": "1a89f428", "metadata": {}, "source": [ "# Cleaning Size" ] }, { "cell_type": "code", "execution_count": 44, "id": "485f039e", "metadata": {}, "outputs": [], "source": [ "# df = df.drop(labels=\"fit_category\", axis=1)\n", "# df = df.drop(labels=\"fit_large\", axis=1)\n", "# df = df.drop(labels=\"fit_small\", axis=1)\n", "# df = df.drop(labels=\"fit_true\", axis=1)\n", "# df = df.drop(labels=\"fit_missing\", axis=1)\n", "\n", "# df.head()" ] }, { "cell_type": "code", "execution_count": 46, "id": "139c3649", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Size (6 uniques): \n", " ['-', 'Half Size Large', 'Half Size Small', 'Slightly Large', 'Slightly Small', 'True To Size']\n" ] }, { "data": { "text/plain": [ "Size\n", "True To Size 797\n", "Slightly Small 231\n", "Half Size Small 59\n", "- 44\n", "Slightly Large 31\n", "Half Size Large 8\n", "Name: count, dtype: int64" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Size\"] = (\n", " df[\"Size\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "size_uniques = df[\"Size\"].dropna().unique()\n", "# size_uniques.sort()\n", "size_uniques = sorted(size_uniques)\n", "print(f\"Size ({len(size_uniques)} uniques): \\n\",size_uniques)\n", "\n", "df[\"Size\"].value_counts().head(20)" ] }, { "cell_type": "code", "execution_count": 47, "id": "fe9461ff", "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BrandNameSizeSize_repr
71NikeAir Zoom Pegasus 38 FlyEase-'-'
73NobullAllday Knit-'-'
74NobullAllday Knit-'-'
92BrooksAnthem 4-'-'
98DiadoraAtomo Star-'-'
186OnCloudsurfer Max-'-'
298AltraExperience Flow 2-'-'
331SauconyFreedom 4-'-'
454AsicsGel Kayano Lite 2-'-'
474AsicsGel Nimbus Lite 3-'-'
556AsicsGT 1000 9-'-'
575SauconyHurricane 25-'-'
585BrooksHyperion Elite 5-'-'
586BrooksHyperion Elite 5-'-'
587BrooksHyperion Elite 5-'-'
614Under ArmourInfinite Pro-'-'
634NobullJourney-'-'
635NobullJourney-'-'
636NobullJourney-'-'
637NobullJourney-'-'
668BrooksLevitate 5-'-'
680BrooksLevitate Stealthfit 5-'-'
681BrooksLevitate Stealthfit 6-'-'
692HokaMach X 3-'-'
839JordanReact Havoc-'-'
866BrooksRicochet 3-'-'
915SalomonS/Lab Phantasm 2-'-'
916SalomonS/Lab Spectur-'-'
954AsicsSonicblast-'-'
955AsicsSonicblast-'-'
956SalomonSpectur 2-'-'
1006Under ArmourSurge 4-'-'
1095NikeVomero Premium-'-'
1129MizunoWave Rider 29-'-'
1130MizunoWave Rider 29-'-'
1131MizunoWave Rider 29-'-'
1132MizunoWave Rider 29-'-'
1133MizunoWave Rider 29-'-'
1134MizunoWave Rider 29-'-'
1135MizunoWave Rider 29-'-'
1136MizunoWave Rider 29-'-'
1137MizunoWave Rider 29-'-'
1156ReebokZig Dynamica 5-'-'
1157ReebokZig Dynamica 5-'-'
\n", "
" ], "text/plain": [ " Brand Name Size Size_repr\n", "71 Nike Air Zoom Pegasus 38 FlyEase - '-'\n", "73 Nobull Allday Knit - '-'\n", "74 Nobull Allday Knit - '-'\n", "92 Brooks Anthem 4 - '-'\n", "98 Diadora Atomo Star - '-'\n", "186 On Cloudsurfer Max - '-'\n", "298 Altra Experience Flow 2 - '-'\n", "331 Saucony Freedom 4 - '-'\n", "454 Asics Gel Kayano Lite 2 - '-'\n", "474 Asics Gel Nimbus Lite 3 - '-'\n", "556 Asics GT 1000 9 - '-'\n", "575 Saucony Hurricane 25 - '-'\n", "585 Brooks Hyperion Elite 5 - '-'\n", "586 Brooks Hyperion Elite 5 - '-'\n", "587 Brooks Hyperion Elite 5 - '-'\n", "614 Under Armour Infinite Pro - '-'\n", "634 Nobull Journey - '-'\n", "635 Nobull Journey - '-'\n", "636 Nobull Journey - '-'\n", "637 Nobull Journey - '-'\n", "668 Brooks Levitate 5 - '-'\n", "680 Brooks Levitate Stealthfit 5 - '-'\n", "681 Brooks Levitate Stealthfit 6 - '-'\n", "692 Hoka Mach X 3 - '-'\n", "839 Jordan React Havoc - '-'\n", "866 Brooks Ricochet 3 - '-'\n", "915 Salomon S/Lab Phantasm 2 - '-'\n", "916 Salomon S/Lab Spectur - '-'\n", "954 Asics Sonicblast - '-'\n", "955 Asics Sonicblast - '-'\n", "956 Salomon Spectur 2 - '-'\n", "1006 Under Armour Surge 4 - '-'\n", "1095 Nike Vomero Premium - '-'\n", "1129 Mizuno Wave Rider 29 - '-'\n", "1130 Mizuno Wave Rider 29 - '-'\n", "1131 Mizuno Wave Rider 29 - '-'\n", "1132 Mizuno Wave Rider 29 - '-'\n", "1133 Mizuno Wave Rider 29 - '-'\n", "1134 Mizuno Wave Rider 29 - '-'\n", "1135 Mizuno Wave Rider 29 - '-'\n", "1136 Mizuno Wave Rider 29 - '-'\n", "1137 Mizuno Wave Rider 29 - '-'\n", "1156 Reebok Zig Dynamica 5 - '-'\n", "1157 Reebok Zig Dynamica 5 - '-'" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mask = df[\"Size\"].astype(str).str.strip() == \"-\"\n", "df.loc[mask, [\"Brand\",\"Name\", \"Size\"]].assign(\n", " Size_repr=df.loc[mask, \"Size\"].apply(repr)\n", ")" ] }, { "cell_type": "markdown", "id": "007b5d56", "metadata": {}, "source": [ "kenapaaaaaaaa............dia.........strip....doang..." ] }, { "cell_type": "code", "execution_count": 48, "id": "cc19d779", "metadata": {}, "outputs": [], "source": [ "size_map = {\n", " \"Half Size Small\": \"small\",\n", " \"Slightly Small\": \"small\",\n", " \"True To Size\": \"true\",\n", " \"Slightly Large\": \"large\",\n", " \"Half Size Large\": \"large\",\n", "}\n", "\n", "df[\"fit_category\"] = df[\"Size\"].map(size_map)" ] }, { "cell_type": "code", "execution_count": 49, "id": "db763764", "metadata": {}, "outputs": [], "source": [ "fit_ohe = pd.get_dummies(df[\"fit_category\"], prefix=\"fit\").astype(int)\n", "\n", "for col in [\"fit_missing\", \"fit_true\", \"fit_small\", \"fit_large\"]:\n", " if col not in fit_ohe.columns:\n", " fit_ohe[col] = 0\n", "\n", "fit_ohe[\"fit_missing\"] = df[\"fit_category\"].isna().astype(int)\n", "\n", "df = pd.concat([df, fit_ohe], axis=1)" ] }, { "cell_type": "code", "execution_count": 50, "id": "a4499637", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fit_missing 44\n", "fit_true 797\n", "fit_small 290\n", "fit_large 39\n", "dtype: int64\n" ] } ], "source": [ "print(df[[\"fit_missing\",\"fit_true\",\"fit_small\",\"fit_large\"]].sum())\n", "assert (\n", " df[[\"fit_missing\",\"fit_true\",\"fit_small\",\"fit_large\"]].sum(axis=1) == 1\n", ").all()" ] }, { "cell_type": "markdown", "id": "526b6a24", "metadata": {}, "source": [ "yang slightly sama half size gitu langsung dimasukin ke kolom kegedean apa kekecilan. hasilnya begitu" ] }, { "cell_type": "code", "execution_count": 51, "id": "27e44d2b", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...Strike_lists-strike_forefootstrike_heelstrike_midfit_categoryfit_largefit_smallfit_truefit_missing
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...[Heel, Mid, Forefoot]0111true0010
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...[Mid, Forefoot]0101true0010
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...[Heel, Mid, Forefoot]0111true0010
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...[Heel]0010small0100
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...[Heel, Mid, Forefoot]0111true0010
\n", "

5 rows × 51 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... Strike_lists - strike_forefoot \\\n", "0 Heelmid/Forefoot ... [Heel, Mid, Forefoot] 0 1 \n", "1 Mid/Forefoot ... [Mid, Forefoot] 0 1 \n", "2 Heelmid/Forefoot ... [Heel, Mid, Forefoot] 0 1 \n", "3 Heel ... [Heel] 0 0 \n", "4 Heelmid/Forefoot ... [Heel, Mid, Forefoot] 0 1 \n", "\n", " strike_heel strike_mid fit_category fit_large fit_small fit_true fit_missing \n", "0 1 1 true 0 0 1 0 \n", "1 0 1 true 0 0 1 0 \n", "2 1 1 true 0 0 1 0 \n", "3 1 0 small 0 1 0 0 \n", "4 1 1 true 0 0 1 0 \n", "\n", "[5 rows x 51 columns]" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 52, "id": "4416dafe", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 1170 entries, 0 to 1169\n", "Data columns (total 51 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 1170 non-null str \n", " 1 Name 1170 non-null str \n", " 2 Audience score 1164 non-null str \n", " 3 Price 1170 non-null str \n", " 4 Pace 1170 non-null str \n", " 5 Arch support 1170 non-null str \n", " 6 Weight lab Weight brand 1170 non-null str \n", " 7 Lightweight 1170 non-null int64 \n", " 8 Drop lab Drop brand 1170 non-null str \n", " 9 Strike pattern 1170 non-null str \n", " 10 Size 1170 non-null str \n", " 11 Midsole softness 1170 non-null str \n", " 12 Toebox durability 1170 non-null str \n", " 13 Heel padding durability 1170 non-null str \n", " 14 Outsole durability 1170 non-null str \n", " 15 Breathability 1170 non-null str \n", " 16 Width / fit 1170 non-null str \n", " 17 Toebox width 1170 non-null str \n", " 18 Stiffness 1170 non-null str \n", " 19 Torsional rigidity 1170 non-null str \n", " 20 Heel counter stiffness 1170 non-null str \n", " 21 Plate 1170 non-null str \n", " 22 Rocker 1170 non-null int64 \n", " 23 Heel lab Heel brand 1170 non-null str \n", " 24 Forefoot lab Forefoot brand 1170 non-null str \n", " 25 Widths available 1170 non-null str \n", " 26 Orthotic friendly 1170 non-null int64 \n", " 27 Season 1170 non-null str \n", " 28 Removable insole 1170 non-null int64 \n", " 29 Ranking 1170 non-null str \n", " 30 Popularity 1170 non-null str \n", " 31 Gender 10 non-null str \n", " 32 Terrain 16 non-null str \n", " 33 Pace_norm 1170 non-null str \n", " 34 Pace_lists 1170 non-null object\n", " 35 pace_competition 1170 non-null int64 \n", " 36 pace_daily_running 1170 non-null int64 \n", " 37 pace_tempo 1170 non-null int64 \n", " 38 arch_neutral 1170 non-null int64 \n", " 39 arch_stability 1170 non-null int64 \n", " 40 Strike_norm 1170 non-null str \n", " 41 Strike_lists 1170 non-null object\n", " 42 - 1170 non-null int64 \n", " 43 strike_forefoot 1170 non-null int64 \n", " 44 strike_heel 1170 non-null int64 \n", " 45 strike_mid 1170 non-null int64 \n", " 46 fit_category 1126 non-null str \n", " 47 fit_large 1170 non-null int64 \n", " 48 fit_small 1170 non-null int64 \n", " 49 fit_true 1170 non-null int64 \n", " 50 fit_missing 1170 non-null int64 \n", "dtypes: int64(17), object(2), str(32)\n", "memory usage: 466.3+ KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "code", "execution_count": 53, "id": "dc1856f3", "metadata": {}, "outputs": [], "source": [ "# df.rename(columns={\"-\": \"strike_missing\"}, inplace=True)" ] }, { "cell_type": "markdown", "id": "f9aff0dc", "metadata": {}, "source": [ "# Cleaning Midsole" ] }, { "cell_type": "code", "execution_count": 55, "id": "7a77b6f6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Midsole (4 uniques): \n", " ['-', 'Balanced', 'Firm', 'Soft']\n" ] }, { "data": { "text/plain": [ "Midsole softness\n", "Balanced 543\n", "Soft 504\n", "- 72\n", "Firm 51\n", "Name: count, dtype: int64" ] }, "execution_count": 55, "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": 56, "id": "b8050c57", "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", "
BrandNameMidsole softnessmidsole_repr
25AdidasAdizero Adios Pro 2.0-'-'
53BrooksAdrenaline GTS 22-'-'
70NikeAir Zoom Pegasus 38-'-'
71NikeAir Zoom Pegasus 38 FlyEase-'-'
92BrooksAnthem 4-'-'
...............
1050AdidasUltraboost 21-'-'
1071MerrellVapor Glove 6-'-'
1072MerrellVapor Glove 6-'-'
1124MizunoWave Rider 25-'-'
1158NikeZoom Fly 4-'-'
\n", "

72 rows × 4 columns

\n", "
" ], "text/plain": [ " Brand Name Midsole softness midsole_repr\n", "25 Adidas Adizero Adios Pro 2.0 - '-'\n", "53 Brooks Adrenaline GTS 22 - '-'\n", "70 Nike Air Zoom Pegasus 38 - '-'\n", "71 Nike Air Zoom Pegasus 38 FlyEase - '-'\n", "92 Brooks Anthem 4 - '-'\n", "... ... ... ... ...\n", "1050 Adidas Ultraboost 21 - '-'\n", "1071 Merrell Vapor Glove 6 - '-'\n", "1072 Merrell Vapor Glove 6 - '-'\n", "1124 Mizuno Wave Rider 25 - '-'\n", "1158 Nike Zoom Fly 4 - '-'\n", "\n", "[72 rows x 4 columns]" ] }, "execution_count": 56, "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": 57, "id": "9cb14667", "metadata": {}, "outputs": [], "source": [ "# midsole_map = {\n", " \n", "# }\n", "\n", "# df[\"midsole_category\"] = df[\"Midsole softness\"].map(midsole_map)" ] }, { "cell_type": "code", "execution_count": 58, "id": "27c8c72b", "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": 59, "id": "5f2d647e", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...strike_heelstrike_midfit_categoryfit_largefit_smallfit_truefit_missingmidsole_softmidsole_balancedmidsole_firm
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...11true0010010
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...01true0010100
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...11true0010001
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...10small0100001
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...11true0010001
\n", "

5 rows × 54 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... strike_heel strike_mid fit_category fit_large \\\n", "0 Heelmid/Forefoot ... 1 1 true 0 \n", "1 Mid/Forefoot ... 0 1 true 0 \n", "2 Heelmid/Forefoot ... 1 1 true 0 \n", "3 Heel ... 1 0 small 0 \n", "4 Heelmid/Forefoot ... 1 1 true 0 \n", "\n", " fit_small fit_true fit_missing midsole_soft midsole_balanced midsole_firm \n", "0 0 1 0 0 1 0 \n", "1 0 1 0 1 0 0 \n", "2 0 1 0 0 0 1 \n", "3 1 0 0 0 0 1 \n", "4 0 1 0 0 0 1 \n", "\n", "[5 rows x 54 columns]" ] }, "execution_count": 59, "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": 60, "id": "1bd6f66d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "Soft: 504\n", "Balanced: 543\n", "Firm: 51\n", "Missing midsole softness rows: 72\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": "markdown", "id": "341e1a94", "metadata": {}, "source": [ "maaf kalo kurang berprinsip, nanti deh analisis asumsi rangkuman itunya" ] }, { "cell_type": "markdown", "id": "31a9f82e", "metadata": {}, "source": [ "### Analisis Midsole Softness \n", "A. Soft\n", "Rasa: empuk, plush, compressible\n", "Cocok untuk: easy run, long run, recovery\n", "Kelebihan: nyaman, ramah kaki, menyerap impact\n", "Kekurangan: responsivitas lebih rendah, bisa terasa “tenggelam” saat ngebut\n", "\n", "B. Balanced\n", "Rasa: seimbang antara empuk dan firm\n", "Cocok untuk: daily running serbaguna, tempo ringan\n", "Kelebihan: stabil, fleksibel, paling aman untuk mayoritas pelari\n", "Kekurangan: tidak se-empuk soft, tidak se-responsif firm\n", "\n", "C. Firm\n", "Rasa: padat, minim kompresi\n", "Cocok untuk: tempo run, interval, racing\n", "Kelebihan: responsif, efisien energi, stabil saat pace cepat\n", "Kekurangan: kurang nyaman untuk jarak jauh santai" ] }, { "cell_type": "markdown", "id": "a6e28c3a", "metadata": {}, "source": [ "# Cleaning Toebox durability" ] }, { "cell_type": "code", "execution_count": 62, "id": "13d90252", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Toebox (4 uniques): \n", " ['-', 'Bad', 'Decent', 'Good']\n" ] }, { "data": { "text/plain": [ "Toebox durability\n", "Decent 486\n", "Bad 263\n", "Good 247\n", "- 174\n", "Name: count, dtype: int64" ] }, "execution_count": 62, "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": 63, "id": "1a7d7688", "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": 64, "id": "98e49c7a", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...fit_largefit_smallfit_truefit_missingmidsole_softmidsole_balancedmidsole_firmtoebox_badtoebox_decenttoebox_good
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0010010000
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0010100001
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0010001000
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0100001000
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0010001001
\n", "

5 rows × 57 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... fit_large fit_small fit_true fit_missing \\\n", "0 Heelmid/Forefoot ... 0 0 1 0 \n", "1 Mid/Forefoot ... 0 0 1 0 \n", "2 Heelmid/Forefoot ... 0 0 1 0 \n", "3 Heel ... 0 1 0 0 \n", "4 Heelmid/Forefoot ... 0 0 1 0 \n", "\n", " midsole_soft midsole_balanced midsole_firm toebox_bad toebox_decent \\\n", "0 0 1 0 0 0 \n", "1 1 0 0 0 0 \n", "2 0 0 1 0 0 \n", "3 0 0 1 0 0 \n", "4 0 0 1 0 0 \n", "\n", " toebox_good \n", "0 0 \n", "1 1 \n", "2 0 \n", "3 0 \n", "4 1 \n", "\n", "[5 rows x 57 columns]" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 65, "id": "1e4ee12e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "Bad: 263\n", "Decent: 486\n", "Good: 247\n", "Missing toebox rows: 174\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": "markdown", "id": "5c40a81d", "metadata": {}, "source": [ "### Analisis Toebox Durability\n", "Toebox durability menggambarkan ketahanan bagian depan sepatu (area jari kaki) terhadap aus, robek, atau jebol akibat gesekan dan tekanan saat berlari. Fitur ini tidak berhubungan dengan kenyamanan, tapi umur pakai sepatu, terutama untuk pelari dengan tekanan forefoot tinggi atau mileage besar.\n", "\n", "A. Bad = Toebox mudah aus / cepat rusak\n", "Umum pada sepatu:\n", "- sangat ringan\n", "- racing-oriented\n", "Risiko: cepat jebol jika dipakai intens\n", "Trade-off: biasanya lebih breathable & ringan\n", "\n", "B. Decent = Ketahanan cukup untuk pemakaian normal\n", "Aman untuk:\n", "- daily running\n", "- latihan reguler\n", "Trade-off: tidak sekuat kategori “Good”, tapi seimbang\n", "\n", "C. Good = Toebox kuat dan tahan lama\n", "Cocok untuk:\n", "- mileage tinggi\n", "- forefoot striker\n", "- pemakaian kasar / jangka panjang\n", "Trade-off: kadang sedikit lebih berat atau kurang breathable" ] }, { "cell_type": "markdown", "id": "db78fbae", "metadata": {}, "source": [ "# Cleaning Heel padding durability" ] }, { "cell_type": "code", "execution_count": 67, "id": "0e7f91f1", "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 555\n", "Decent 248\n", "Bad 191\n", "- 176\n", "Name: count, dtype: int64" ] }, "execution_count": 67, "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": 68, "id": "7c9c18c7", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...fit_missingmidsole_softmidsole_balancedmidsole_firmtoebox_badtoebox_decenttoebox_goodheelpad_badheelpad_decentheelpad_good
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0010000000
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0100001001
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0001000001
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0001000000
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0001001001
\n", "

5 rows × 60 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... fit_missing midsole_soft midsole_balanced \\\n", "0 Heelmid/Forefoot ... 0 0 1 \n", "1 Mid/Forefoot ... 0 1 0 \n", "2 Heelmid/Forefoot ... 0 0 0 \n", "3 Heel ... 0 0 0 \n", "4 Heelmid/Forefoot ... 0 0 0 \n", "\n", " midsole_firm toebox_bad toebox_decent toebox_good heelpad_bad \\\n", "0 0 0 0 0 0 \n", "1 0 0 0 1 0 \n", "2 1 0 0 0 0 \n", "3 1 0 0 0 0 \n", "4 1 0 0 1 0 \n", "\n", " heelpad_decent heelpad_good \n", "0 0 0 \n", "1 0 1 \n", "2 0 1 \n", "3 0 0 \n", "4 0 1 \n", "\n", "[5 rows x 60 columns]" ] }, "execution_count": 68, "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": 69, "id": "0cdc7d72", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "Bad: 191\n", "Decent: 248\n", "Good: 555\n", "Missing heelpad durability rows: 176\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": "markdown", "id": "44af6117", "metadata": {}, "source": [ "makin banyak missingnya bre" ] }, { "cell_type": "markdown", "id": "b7225f80", "metadata": {}, "source": [ "### Analisis Heel Padding Durability\n", "Heel padding durability menggambarkan ketahanan bantalan di area tumit bagian dalam sepatu terhadap aus, kempes, atau rusak akibat gesekan dan tekanan berulang saat berlari. Fitur ini berpengaruh pada kenyamanan jangka panjang, stabilitas tumit, dan umur pakai sepatu, terutama bagi pelari yang dominan heel strike.\n", "\n", "Bad: \n", "Bantalan tumit cepat aus atau kempes\n", "Berpotensi menyebabkan:\n", "rasa tidak nyaman\n", "gesekan berlebih di tumit\n", "Umum pada sepatu:\n", "ringan\n", "fokus ke performa jangka pendek\n", "Trade-off: bobot lebih ringan, tapi durability rendah\n", "\n", "Decent: \n", "Ketahanan bantalan cukup untuk pemakaian normal\n", "Aman untuk:\n", "daily running\n", "latihan reguler\n", "Trade-off: tidak sekuat kategori “Good”, tapi seimbang\n", "\n", "Good: \n", "Bantalan tumit kuat dan tahan lama\n", "Cocok untuk:\n", "mileage tinggi\n", "pemakaian jangka panjang\n", "pelari heel strike\n", "Trade-off: kadang sedikit lebih berat atau kurang breathable" ] }, { "cell_type": "markdown", "id": "00d5e6f9", "metadata": {}, "source": [ "# Cleaning Outsole Durability" ] }, { "cell_type": "code", "execution_count": 71, "id": "cc9ba6e9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Outsole (4 uniques): \n", " ['-', 'Bad', 'Decent', 'Good']\n" ] }, { "data": { "text/plain": [ "Outsole durability\n", "Good 631\n", "Decent 253\n", "- 209\n", "Bad 77\n", "Name: count, dtype: int64" ] }, "execution_count": 71, "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": 72, "id": "28bf5e69", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...midsole_firmtoebox_badtoebox_decenttoebox_goodheelpad_badheelpad_decentheelpad_goodoutsole_badoutsole_decentoutsole_good
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0000000000
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0001001001
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...1000001000
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...1000000000
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...1001001001
\n", "

5 rows × 63 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... midsole_firm toebox_bad toebox_decent toebox_good \\\n", "0 Heelmid/Forefoot ... 0 0 0 0 \n", "1 Mid/Forefoot ... 0 0 0 1 \n", "2 Heelmid/Forefoot ... 1 0 0 0 \n", "3 Heel ... 1 0 0 0 \n", "4 Heelmid/Forefoot ... 1 0 0 1 \n", "\n", " heelpad_bad heelpad_decent heelpad_good outsole_bad outsole_decent \\\n", "0 0 0 0 0 0 \n", "1 0 0 1 0 0 \n", "2 0 0 1 0 0 \n", "3 0 0 0 0 0 \n", "4 0 0 1 0 0 \n", "\n", " outsole_good \n", "0 0 \n", "1 1 \n", "2 0 \n", "3 0 \n", "4 1 \n", "\n", "[5 rows x 63 columns]" ] }, "execution_count": 72, "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": 73, "id": "6e11f54a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "outsole_bad 77\n", "outsole_decent 253\n", "outsole_good 631\n", "dtype: int64\n", "Missing outsole rows: 209\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"outsole_bad\",\"outsole_decent\",\"outsole_good\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# single-label atau missing\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": "markdown", "id": "74ad3110", "metadata": {}, "source": [ "### Analisis Outsole Durability\n", "\n", "Outsole durability menggambarkan ketahanan sol bagian bawah sepatu terhadap aus akibat kontak langsung dengan permukaan lari (aspal, beton, treadmill, track).\n", "\n", "Fitur ini berhubungan langsung dengan umur pakai sepatu dan efisiensi biaya, terutama bagi pelari dengan mileage tinggi atau yang sering berlari di permukaan keras.\n", "\n", "- Bad: \n", "Outsole cepat aus\n", "Grip dan perlindungan cepat menurun\n", "Umum pada sepatu:\n", "ringan\n", "racing-oriented\n", "Trade-off: bobot ringan, tapi umur pakai pendek\n", "\n", "- Decent: \n", "Ketahanan cukup untuk pemakaian normal\n", "Aman untuk:\n", "daily running\n", "latihan reguler\n", "Trade-off: bukan yang paling awet, tapi seimbang\n", "\n", "- Good: \n", "Outsole sangat tahan lama\n", "Cocok untuk:\n", "mileage tinggi\n", "pemakaian jangka panjang\n", "lari di permukaan kasar\n", "Trade-off: kadang lebih berat atau kurang fleksibel" ] }, { "cell_type": "markdown", "id": "f0da23b5", "metadata": {}, "source": [ "# Cleaning Breathability" ] }, { "cell_type": "code", "execution_count": 74, "id": "5953a816", "metadata": {}, "outputs": [], "source": [ "# df = df.drop(labels=\"breathable\", axis=1)\n", "# df = df.drop(labels=\"moderate\", axis=1)\n", "# df = df.drop(labels=\"warm\", axis=1)\n", "# df.head()" ] }, { "cell_type": "code", "execution_count": 76, "id": "b90e8e6c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Breathability (4 uniques): \n", " ['-', 'Breathable', 'Moderate', 'Warm']\n" ] }, { "data": { "text/plain": [ "Breathability\n", "Moderate 642\n", "Breathable 347\n", "Warm 118\n", "- 63\n", "Name: count, dtype: int64" ] }, "execution_count": 76, "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": 77, "id": "61b2650b", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...toebox_goodheelpad_badheelpad_decentheelpad_goodoutsole_badoutsole_decentoutsole_goodbreath_breathablebreath_moderatebreath_warm
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0000000000
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...1001001100
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0001000001
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0000000001
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...1001001001
\n", "

5 rows × 66 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... toebox_good heelpad_bad heelpad_decent heelpad_good \\\n", "0 Heelmid/Forefoot ... 0 0 0 0 \n", "1 Mid/Forefoot ... 1 0 0 1 \n", "2 Heelmid/Forefoot ... 0 0 0 1 \n", "3 Heel ... 0 0 0 0 \n", "4 Heelmid/Forefoot ... 1 0 0 1 \n", "\n", " outsole_bad outsole_decent outsole_good breath_breathable breath_moderate \\\n", "0 0 0 0 0 0 \n", "1 0 0 1 1 0 \n", "2 0 0 0 0 0 \n", "3 0 0 0 0 0 \n", "4 0 0 1 0 0 \n", "\n", " breath_warm \n", "0 0 \n", "1 0 \n", "2 1 \n", "3 1 \n", "4 1 \n", "\n", "[5 rows x 66 columns]" ] }, "execution_count": 77, "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": 78, "id": "06e99a17", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "breath_breathable 347\n", "breath_moderate 642\n", "breath_warm 118\n", "dtype: int64\n", "Missing breathability rows: 63\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"breath_breathable\",\"breath_moderate\",\"breath_warm\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# single-label atau missing\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": "markdown", "id": "0d08520e", "metadata": {}, "source": [ "### Analisis Breathability\n", "\n", "Breathability menggambarkan seberapa baik sepatu memungkinkan sirkulasi udara di bagian upper, yang berpengaruh pada suhu kaki, kenyamanan, dan manajemen kelembapan saat berlari.\n", "\n", "Fitur ini penting terutama untuk:\n", "\n", "lari jarak jauh\n", "\n", "cuaca panas\n", "\n", "pelari dengan kaki mudah berkeringat\n", "\n", "Breathable\n", "\n", "Sirkulasi udara sangat baik\n", "\n", "Kaki terasa lebih sejuk dan kering\n", "\n", "Cocok untuk:\n", "\n", "cuaca panas\n", "\n", "long run\n", "\n", "Trade-off: biasanya material lebih tipis → durability bisa lebih rendah\n", "\n", "Moderate\n", "\n", "Sirkulasi udara cukup / seimbang\n", "\n", "Aman untuk pemakaian umum\n", "\n", "Cocok untuk:\n", "\n", "daily running\n", "\n", "berbagai kondisi cuaca\n", "\n", "Trade-off: tidak seadem “Breathable”, tidak sehangat “Warm”\n", "\n", "Warm\n", "\n", "Ventilasi minim\n", "\n", "Menjaga kaki tetap hangat\n", "\n", "Cocok untuk:\n", "\n", "cuaca dingin\n", "\n", "winter running\n", "\n", "Trade-off: kaki bisa terasa panas di cuaca hangat" ] }, { "cell_type": "markdown", "id": "9b7c347e", "metadata": {}, "source": [ "# Cleaning Width / fit" ] }, { "cell_type": "code", "execution_count": 80, "id": "4c25ac2d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Width / fit (3 uniques): \n", " ['Medium', 'Narrow', 'Wide']\n" ] }, { "data": { "text/plain": [ "Width / fit\n", "Medium 786\n", "Narrow 287\n", "Wide 97\n", "Name: count, dtype: int64" ] }, "execution_count": 80, "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": 81, "id": "d33d3ef6", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...heelpad_goodoutsole_badoutsole_decentoutsole_goodbreath_breathablebreath_moderatebreath_warmwidth_narrowwidth_mediumwidth_wide
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0000000100
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...1001100100
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...1000001100
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0000001100
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...1001001100
\n", "

5 rows × 69 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... heelpad_good outsole_bad outsole_decent outsole_good \\\n", "0 Heelmid/Forefoot ... 0 0 0 0 \n", "1 Mid/Forefoot ... 1 0 0 1 \n", "2 Heelmid/Forefoot ... 1 0 0 0 \n", "3 Heel ... 0 0 0 0 \n", "4 Heelmid/Forefoot ... 1 0 0 1 \n", "\n", " breath_breathable breath_moderate breath_warm width_narrow width_medium \\\n", "0 0 0 0 1 0 \n", "1 1 0 0 1 0 \n", "2 0 0 1 1 0 \n", "3 0 0 1 1 0 \n", "4 0 0 1 1 0 \n", "\n", " width_wide \n", "0 0 \n", "1 0 \n", "2 0 \n", "3 0 \n", "4 0 \n", "\n", "[5 rows x 69 columns]" ] }, "execution_count": 81, "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": 82, "id": "1ec7610a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "width_narrow 287\n", "width_medium 786\n", "width_wide 97\n", "dtype: int64\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"width_narrow\",\"width_medium\",\"width_wide\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# HARUS tepat satu (tidak ada missing)\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": "markdown", "id": "cf698833", "metadata": {}, "source": [ "### Analisis Width / Fit\n", "\n", "Width / fit menggambarkan lebar sepatu pada bagian forefoot (area depan kaki), yang memengaruhi kenyamanan, stabilitas, dan risiko lecet saat berlari.\n", "\n", "Fitur ini bukan soal ukuran panjang (EU/US), melainkan ruang horizontal untuk kaki.\n", "\n", "Narrow\n", "\n", "Sepatu terasa lebih sempit dari standar\n", "\n", "Cocok untuk:\n", "\n", "kaki ramping\n", "\n", "pelari yang suka fit ketat\n", "\n", "Risiko: tekanan di sisi kaki jika dipakai oleh kaki lebar\n", "\n", "Medium\n", "\n", "Lebar standar / normal\n", "\n", "Cocok untuk:\n", "\n", "mayoritas pelari\n", "\n", "Catatan: ini adalah default fit di pasaran\n", "\n", "Wide\n", "\n", "Sepatu menyediakan ruang lebih lega\n", "\n", "Cocok untuk:\n", "\n", "kaki lebar\n", "\n", "pelari yang sering merasa jari tertekan\n", "\n", "Trade-off: bisa terasa kurang “locked-in” untuk kaki sempit" ] }, { "cell_type": "code", "execution_count": 83, "id": "928c5523", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 1170 entries, 0 to 1169\n", "Data columns (total 69 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Brand 1170 non-null str \n", " 1 Name 1170 non-null str \n", " 2 Audience score 1164 non-null str \n", " 3 Price 1170 non-null str \n", " 4 Pace 1170 non-null str \n", " 5 Arch support 1170 non-null str \n", " 6 Weight lab Weight brand 1170 non-null str \n", " 7 Lightweight 1170 non-null int64 \n", " 8 Drop lab Drop brand 1170 non-null str \n", " 9 Strike pattern 1170 non-null str \n", " 10 Size 1170 non-null str \n", " 11 Midsole softness 1170 non-null str \n", " 12 Toebox durability 1170 non-null str \n", " 13 Heel padding durability 1170 non-null str \n", " 14 Outsole durability 1170 non-null str \n", " 15 Breathability 1170 non-null str \n", " 16 Width / fit 1170 non-null str \n", " 17 Toebox width 1170 non-null str \n", " 18 Stiffness 1170 non-null str \n", " 19 Torsional rigidity 1170 non-null str \n", " 20 Heel counter stiffness 1170 non-null str \n", " 21 Plate 1170 non-null str \n", " 22 Rocker 1170 non-null int64 \n", " 23 Heel lab Heel brand 1170 non-null str \n", " 24 Forefoot lab Forefoot brand 1170 non-null str \n", " 25 Widths available 1170 non-null str \n", " 26 Orthotic friendly 1170 non-null int64 \n", " 27 Season 1170 non-null str \n", " 28 Removable insole 1170 non-null int64 \n", " 29 Ranking 1170 non-null str \n", " 30 Popularity 1170 non-null str \n", " 31 Gender 10 non-null str \n", " 32 Terrain 16 non-null str \n", " 33 Pace_norm 1170 non-null str \n", " 34 Pace_lists 1170 non-null object\n", " 35 pace_competition 1170 non-null int64 \n", " 36 pace_daily_running 1170 non-null int64 \n", " 37 pace_tempo 1170 non-null int64 \n", " 38 arch_neutral 1170 non-null int64 \n", " 39 arch_stability 1170 non-null int64 \n", " 40 Strike_norm 1170 non-null str \n", " 41 Strike_lists 1170 non-null object\n", " 42 - 1170 non-null int64 \n", " 43 strike_forefoot 1170 non-null int64 \n", " 44 strike_heel 1170 non-null int64 \n", " 45 strike_mid 1170 non-null int64 \n", " 46 fit_category 1126 non-null str \n", " 47 fit_large 1170 non-null int64 \n", " 48 fit_small 1170 non-null int64 \n", " 49 fit_true 1170 non-null int64 \n", " 50 fit_missing 1170 non-null int64 \n", " 51 midsole_soft 1170 non-null int64 \n", " 52 midsole_balanced 1170 non-null int64 \n", " 53 midsole_firm 1170 non-null int64 \n", " 54 toebox_bad 1170 non-null int64 \n", " 55 toebox_decent 1170 non-null int64 \n", " 56 toebox_good 1170 non-null int64 \n", " 57 heelpad_bad 1170 non-null int64 \n", " 58 heelpad_decent 1170 non-null int64 \n", " 59 heelpad_good 1170 non-null int64 \n", " 60 outsole_bad 1170 non-null int64 \n", " 61 outsole_decent 1170 non-null int64 \n", " 62 outsole_good 1170 non-null int64 \n", " 63 breath_breathable 1170 non-null int64 \n", " 64 breath_moderate 1170 non-null int64 \n", " 65 breath_warm 1170 non-null int64 \n", " 66 width_narrow 1170 non-null int64 \n", " 67 width_medium 1170 non-null int64 \n", " 68 width_wide 1170 non-null int64 \n", "dtypes: int64(35), object(2), str(32)\n", "memory usage: 630.8+ KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "markdown", "id": "9df086d9", "metadata": {}, "source": [ "# Cleaning Toebox Width" ] }, { "cell_type": "code", "execution_count": 85, "id": "d88dbf71", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Toebox width (4 uniques): \n", " ['-', 'Medium', 'Narrow', 'Wide']\n" ] }, { "data": { "text/plain": [ "Toebox width\n", "Medium 669\n", "Wide 179\n", "Narrow 170\n", "- 152\n", "Name: count, dtype: int64" ] }, "execution_count": 85, "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": 86, "id": "8cb44aed", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...outsole_goodbreath_breathablebreath_moderatebreath_warmwidth_narrowwidth_mediumwidth_widetoeboxwidth_narrowtoeboxwidth_mediumtoeboxwidth_wide
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0000100000
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...1100100010
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0001100000
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0001100000
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...1001100010
\n", "

5 rows × 72 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... outsole_good breath_breathable breath_moderate \\\n", "0 Heelmid/Forefoot ... 0 0 0 \n", "1 Mid/Forefoot ... 1 1 0 \n", "2 Heelmid/Forefoot ... 0 0 0 \n", "3 Heel ... 0 0 0 \n", "4 Heelmid/Forefoot ... 1 0 0 \n", "\n", " breath_warm width_narrow width_medium width_wide toeboxwidth_narrow \\\n", "0 0 1 0 0 0 \n", "1 0 1 0 0 0 \n", "2 1 1 0 0 0 \n", "3 1 1 0 0 0 \n", "4 1 1 0 0 0 \n", "\n", " toeboxwidth_medium toeboxwidth_wide \n", "0 0 0 \n", "1 1 0 \n", "2 0 0 \n", "3 0 0 \n", "4 1 0 \n", "\n", "[5 rows x 72 columns]" ] }, "execution_count": 86, "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": 87, "id": "8615c63c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "toeboxwidth_narrow 170\n", "toeboxwidth_medium 669\n", "toeboxwidth_wide 179\n", "dtype: int64\n", "Missing toebox width rows: 152\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": "markdown", "id": "1a0c1581", "metadata": {}, "source": [ "### Analisis Toebox Width\n", "\n", "Toebox width menggambarkan lebar ruang di bagian depan sepatu (area jari kaki).\n", "Fitur ini memengaruhi kenyamanan jari, risiko lecet, dan rasa sempit/lega saat berlari, terutama pada jarak jauh.\n", "\n", "Berbeda dengan Width / fit (lebar sepatu secara umum), toebox width fokus ke area jari kaki.\n", "\n", "Narrow\n", "\n", "Ruang jari sempit\n", "\n", "Cocok untuk:\n", "\n", "kaki ramping\n", "\n", "pelari yang suka fit ketat\n", "\n", "Risiko: tekanan pada jari kaki, potensi lecet\n", "\n", "Medium\n", "\n", "Ruang jari standar\n", "\n", "Cocok untuk:\n", "\n", "mayoritas pelari\n", "\n", "Catatan: ini adalah default di pasaran\n", "\n", "Wide\n", "\n", "Ruang jari lebih lega\n", "\n", "Cocok untuk:\n", "\n", "kaki lebar\n", "\n", "pelari yang sering merasa jari tertekan\n", "\n", "Trade-off: bisa terasa kurang “locked-in” bagi kaki sempit" ] }, { "cell_type": "markdown", "id": "e9b17fa9", "metadata": {}, "source": [ "# Cleaning Stiffness" ] }, { "cell_type": "code", "execution_count": 89, "id": "f11dfa24", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stiffness (4 uniques): \n", " ['-', 'Flexible', 'Moderate', 'Stiff']\n" ] }, { "data": { "text/plain": [ "Stiffness\n", "Moderate 530\n", "Stiff 510\n", "Flexible 114\n", "- 16\n", "Name: count, dtype: int64" ] }, "execution_count": 89, "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": 90, "id": "047339b7", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...breath_warmwidth_narrowwidth_mediumwidth_widetoeboxwidth_narrowtoeboxwidth_mediumtoeboxwidth_widestiff_flexiblestiff_moderatestiff_stiff
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0100000001
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0100010001
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...1100000001
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...1100000001
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...1100010010
\n", "

5 rows × 75 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... breath_warm width_narrow width_medium width_wide \\\n", "0 Heelmid/Forefoot ... 0 1 0 0 \n", "1 Mid/Forefoot ... 0 1 0 0 \n", "2 Heelmid/Forefoot ... 1 1 0 0 \n", "3 Heel ... 1 1 0 0 \n", "4 Heelmid/Forefoot ... 1 1 0 0 \n", "\n", " toeboxwidth_narrow toeboxwidth_medium toeboxwidth_wide stiff_flexible \\\n", "0 0 0 0 0 \n", "1 0 1 0 0 \n", "2 0 0 0 0 \n", "3 0 0 0 0 \n", "4 0 1 0 0 \n", "\n", " stiff_moderate stiff_stiff \n", "0 0 1 \n", "1 0 1 \n", "2 0 1 \n", "3 0 1 \n", "4 1 0 \n", "\n", "[5 rows x 75 columns]" ] }, "execution_count": 90, "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": 91, "id": "3a78b017", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "stiff_flexible 114\n", "stiff_moderate 530\n", "stiff_stiff 510\n", "dtype: int64\n", "Missing stiffness rows: 16\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": "markdown", "id": "7f6bd750", "metadata": {}, "source": [ "### Analisis Stiffness\n", "Stiffness menggambarkan tingkat kekakuan sepatu secara keseluruhan, terutama saat sepatu ditekuk atau diberi beban.\n", "Fitur ini memengaruhi fleksibilitas langkah, responsivitas, dan kenyamanan.\n", "\n", "Berbeda dengan torsional rigidity atau heel counter stiffness, stiffness di sini bersifat global.\n", "\n", "Flexible\n", "\n", "Sepatu mudah ditekuk\n", "\n", "Memberikan rasa:\n", "\n", "natural\n", "\n", "bebas\n", "\n", "Cocok untuk:\n", "\n", "easy run\n", "\n", "pelari yang suka feel santai\n", "\n", "Trade-off: stabilitas & responsivitas lebih rendah\n", "\n", "Moderate\n", "\n", "Kekakuan seimbang\n", "\n", "Cocok untuk:\n", "\n", "daily running\n", "\n", "penggunaan serbaguna\n", "\n", "Catatan: ini kategori paling aman & umum\n", "\n", "Stiff\n", "\n", "Sepatu kaku dan stabil\n", "\n", "Cocok untuk:\n", "\n", "tempo run\n", "\n", "sepatu dengan plate\n", "\n", "lari cepat\n", "\n", "Trade-off: kurang nyaman untuk pace santai atau jarak jauh" ] }, { "cell_type": "markdown", "id": "01d8345b", "metadata": {}, "source": [ "# Cleaning Torsional rigidity" ] }, { "cell_type": "code", "execution_count": 93, "id": "03cdb82f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Torsional rigidity (4 uniques): \n", " ['-', 'Flexible', 'Moderate', 'Stiff']\n" ] }, { "data": { "text/plain": [ "Torsional rigidity\n", "Stiff 610\n", "Moderate 368\n", "Flexible 174\n", "- 18\n", "Name: count, dtype: int64" ] }, "execution_count": 93, "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": 94, "id": "34f7fa79", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...width_widetoeboxwidth_narrowtoeboxwidth_mediumtoeboxwidth_widestiff_flexiblestiff_moderatestiff_stifftorsion_flexibletorsion_moderatetorsion_stiff
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0000001001
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0010001010
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0000001100
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0000001100
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0010010100
\n", "

5 rows × 78 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... width_wide toeboxwidth_narrow toeboxwidth_medium \\\n", "0 Heelmid/Forefoot ... 0 0 0 \n", "1 Mid/Forefoot ... 0 0 1 \n", "2 Heelmid/Forefoot ... 0 0 0 \n", "3 Heel ... 0 0 0 \n", "4 Heelmid/Forefoot ... 0 0 1 \n", "\n", " toeboxwidth_wide stiff_flexible stiff_moderate stiff_stiff torsion_flexible \\\n", "0 0 0 0 1 0 \n", "1 0 0 0 1 0 \n", "2 0 0 0 1 1 \n", "3 0 0 0 1 1 \n", "4 0 0 1 0 1 \n", "\n", " torsion_moderate torsion_stiff \n", "0 0 1 \n", "1 1 0 \n", "2 0 0 \n", "3 0 0 \n", "4 0 0 \n", "\n", "[5 rows x 78 columns]" ] }, "execution_count": 94, "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": 95, "id": "ef8e64fa", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torsion_flexible 174\n", "torsion_moderate 368\n", "torsion_stiff 610\n", "dtype: int64\n", "Missing torsional rigidity rows: 18\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"torsion_flexible\",\"torsion_moderate\",\"torsion_stiff\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# single-label atau missing\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": "markdown", "id": "3236dda7", "metadata": {}, "source": [ "### Analisis Torsional Rigidity\n", "\n", "Torsional rigidity menggambarkan seberapa sulit sepatu dipuntir (twist) dari depan ke belakang.\n", "Fitur ini berhubungan dengan stabilitas lateral, kontrol kaki, dan dukungan saat mendarat.\n", "\n", "Berbeda dengan overall stiffness (tekuk depan-belakang), torsional rigidity fokus pada puntiran samping.\n", "\n", "Flexible\n", "\n", "Sepatu mudah dipuntir\n", "\n", "Memberikan feel:\n", "\n", "natural\n", "\n", "bebas\n", "\n", "Cocok untuk:\n", "\n", "pelari dengan gait stabil\n", "\n", "easy run\n", "\n", "Trade-off: stabilitas lebih rendah\n", "\n", "Moderate\n", "\n", "Tingkat puntiran seimbang\n", "\n", "Cocok untuk:\n", "\n", "daily running\n", "\n", "mayoritas pelari\n", "\n", "Catatan: kategori paling aman & umum\n", "\n", "Stiff\n", "\n", "Sepatu sulit dipuntir\n", "\n", "Memberikan:\n", "\n", "stabilitas tinggi\n", "\n", "kontrol tambahan\n", "\n", "Cocok untuk:\n", "\n", "pelari yang butuh support\n", "\n", "sepatu berstruktur / plated\n", "\n", "Trade-off: feel lebih kaku" ] }, { "cell_type": "markdown", "id": "d8a7b505", "metadata": {}, "source": [ "# Cleaning Heel counter stiffness" ] }, { "cell_type": "code", "execution_count": 97, "id": "b617da2f", "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 419\n", "Stiff 368\n", "Flexible 351\n", "- 32\n", "Name: count, dtype: int64" ] }, "execution_count": 97, "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": 98, "id": "f477af46", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...toeboxwidth_widestiff_flexiblestiff_moderatestiff_stifftorsion_flexibletorsion_moderatetorsion_stiffheelcounter_flexibleheelcounter_moderateheelcounter_stiff
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0001001100
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0001010010
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0001100100
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0001100010
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0010100100
\n", "

5 rows × 81 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... toeboxwidth_wide stiff_flexible stiff_moderate \\\n", "0 Heelmid/Forefoot ... 0 0 0 \n", "1 Mid/Forefoot ... 0 0 0 \n", "2 Heelmid/Forefoot ... 0 0 0 \n", "3 Heel ... 0 0 0 \n", "4 Heelmid/Forefoot ... 0 0 1 \n", "\n", " stiff_stiff torsion_flexible torsion_moderate torsion_stiff \\\n", "0 1 0 0 1 \n", "1 1 0 1 0 \n", "2 1 1 0 0 \n", "3 1 1 0 0 \n", "4 0 1 0 0 \n", "\n", " heelcounter_flexible heelcounter_moderate heelcounter_stiff \n", "0 1 0 0 \n", "1 0 1 0 \n", "2 1 0 0 \n", "3 0 1 0 \n", "4 1 0 0 \n", "\n", "[5 rows x 81 columns]" ] }, "execution_count": 98, "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": 99, "id": "9b91e5e5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "heelcounter_flexible 351\n", "heelcounter_moderate 419\n", "heelcounter_stiff 368\n", "dtype: int64\n", "Missing heel counter rows: 32\n" ] } ], "source": [ "# hanya 0 / 1\n", "for c in [\"heelcounter_flexible\",\"heelcounter_moderate\",\"heelcounter_stiff\"]:\n", " assert set(df[c].unique()).issubset({0, 1})\n", "\n", "# single-label atau missing\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": "markdown", "id": "0528c1ca", "metadata": {}, "source": [ "### Analisis Heel Counter Stiffness\n", "\n", "Heel counter stiffness menggambarkan tingkat kekakuan struktur di bagian tumit belakang sepatu (heel counter), yang berfungsi menjaga tumit tetap stabil dan terkunci saat berlari.\n", "\n", "Fitur ini berpengaruh pada stabilitas tumit, kontrol kaki, dan rasa aman saat mendarat, terutama untuk pelari heel strike atau yang membutuhkan support tambahan.\n", "\n", "Flexible\n", "\n", "Heel counter mudah ditekan\n", "\n", "Memberikan rasa:\n", "\n", "lebih nyaman\n", "\n", "lebih natural\n", "\n", "Cocok untuk:\n", "\n", "pelari dengan gait stabil\n", "\n", "sepatu santai / fleksibel\n", "\n", "Trade-off: stabilitas tumit lebih rendah\n", "\n", "Moderate\n", "\n", "Kekakuan seimbang\n", "\n", "Cocok untuk:\n", "\n", "daily running\n", "\n", "mayoritas pelari\n", "\n", "Catatan: ini kategori paling aman & umum\n", "\n", "Stiff\n", "\n", "Heel counter kaku dan kokoh\n", "\n", "Memberikan:\n", "\n", "stabilitas tumit tinggi\n", "\n", "rasa “locked-in”\n", "\n", "Cocok untuk:\n", "\n", "pelari yang butuh support\n", "\n", "sepatu berstruktur / plated\n", "\n", "Trade-off: bisa terasa kurang nyaman bagi sebagian orang" ] }, { "cell_type": "markdown", "id": "515d8b22", "metadata": {}, "source": [ "# Cleaning Widths available" ] }, { "cell_type": "code", "execution_count": 101, "id": "3b3f7bec", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Widths available (11 uniques): \n", " ['Narrow Normal Wide X-Wide', 'Narrownormal', 'Narrownormalwide', 'Narrownormalwidex-Wide', 'Narrownormalx-Wide', 'Normal', 'Normal Wide', 'Normal Wide X-Wide', 'Normalwide', 'Normalwidex-Wide', 'Normalx-Wide']\n" ] }, { "data": { "text/plain": [ "Widths available\n", "Normal 537\n", "Normalwide 353\n", "Normalwidex-Wide 166\n", "Narrownormalwidex-Wide 68\n", "Narrownormal 19\n", "Normalx-Wide 18\n", "Narrownormalwide 4\n", "Normal Wide X-Wide 2\n", "Narrow Normal Wide X-Wide 1\n", "Normal Wide 1\n", "Narrownormalx-Wide 1\n", "Name: count, dtype: int64" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"Widths available\"] = (\n", " df[\"Widths available\"]\n", " .astype(str)\n", " .str.strip()\n", " .str.replace(r\"\\s+\", \" \", regex=True)\n", " .str.title()\n", ")\n", "\n", "widths_available_uniques = df[\"Widths available\"].dropna().unique()\n", "# widths_available_uniques.sort()\n", "widths_available_uniques = sorted(widths_available_uniques)\n", "print(f\"Widths available ({len(widths_available_uniques)} uniques): \\n\",widths_available_uniques)\n", "\n", "df[\"Widths available\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 102, "id": "23a2a180", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "UNMAPPED Widths available values:\n", " Series([], Name: count, dtype: int64)\n" ] } ], "source": [ "wa_map = {\n", " \"Normal\": \"Normal\",\n", " \"Normalwide\": \"Normal|Wide\",\n", " \"Normalwidex-Wide\": \"Normal|Wide|X-Wide\",\n", " \"Narrownormalwidex-Wide\": \"Narrow|Normal|Wide|X-Wide\",\n", " \"Normalx-Wide\": \"Normal|X-Wide\",\n", " \"Narrownormal\": \"Narrow|Normal\",\n", " \"Narrownormalwide\": \"Narrow|Normal|Wide\",\n", " \"Normal Wide X-Wide\": \"Normal|Wide|X-Wide\",\n", " \"Narrow Normal Wide X-Wide\": \"Narrow|Normal|Wide|X-Wide\",\n", " \"Normal Wide\": \"Normal|Wide\",\n", " \"Narrownormalx-Wide\": \"Narrow|Normal|X-Wide\",\n", "}\n", "\n", "df[\"widthavail_norm\"] = df[\"Widths available\"].map(wa_map)\n", "\n", "unmapped = df[df[\"widthavail_norm\"].isna()][\"Widths available\"].value_counts()\n", "print(\"UNMAPPED Widths available values:\\n\", unmapped)\n", "assert df[\"widthavail_norm\"].notna().all()" ] }, { "cell_type": "code", "execution_count": 103, "id": "211dba05", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Widths available - norm: (8) uniques\n", " \n", "[ 'Normal|Wide', 'Normal',\n", " 'Narrow|Normal|Wide|X-Wide', 'Normal|X-Wide',\n", " 'Narrow|Normal|Wide', 'Normal|Wide|X-Wide',\n", " 'Narrow|Normal', 'Narrow|Normal|X-Wide']\n", "Length: 8, dtype: str\n", "widthavail_norm\n", "Normal 537\n", "Normal|Wide 354\n", "Normal|Wide|X-Wide 168\n", "Narrow|Normal|Wide|X-Wide 69\n", "Narrow|Normal 19\n", "Normal|X-Wide 18\n", "Narrow|Normal|Wide 4\n", "Narrow|Normal|X-Wide 1\n", "Name: count, dtype: int64\n" ] } ], "source": [ "wa_norm_unique = df[\"widthavail_norm\"].dropna().unique()\n", "print(f'Widths available - norm: ({len(wa_norm_unique)}) uniques\\n', wa_norm_unique)\n", "\n", "print(df[\"widthavail_norm\"].value_counts())" ] }, { "cell_type": "code", "execution_count": 104, "id": "b63b2f3e", "metadata": {}, "outputs": [], "source": [ "df[\"widthavail_list\"] = df[\"widthavail_norm\"].str.split(\"|\")" ] }, { "cell_type": "code", "execution_count": 105, "id": "17dee763", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...torsion_stiffheelcounter_flexibleheelcounter_moderateheelcounter_stiffwidthavail_normwidthavail_listwidthavail_narrowwidthavail_normalwidthavail_widewidthavail_xwide
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...1100Normal|Wide[Normal, Wide]0110
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0010Normal[Normal]0100
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0100Normal[Normal]0100
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0010Normal[Normal]0100
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0100Normal[Normal]0100
\n", "

5 rows × 87 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... torsion_stiff heelcounter_flexible \\\n", "0 Heelmid/Forefoot ... 1 1 \n", "1 Mid/Forefoot ... 0 0 \n", "2 Heelmid/Forefoot ... 0 1 \n", "3 Heel ... 0 0 \n", "4 Heelmid/Forefoot ... 0 1 \n", "\n", " heelcounter_moderate heelcounter_stiff widthavail_norm widthavail_list \\\n", "0 0 0 Normal|Wide [Normal, Wide] \n", "1 1 0 Normal [Normal] \n", "2 0 0 Normal [Normal] \n", "3 1 0 Normal [Normal] \n", "4 0 0 Normal [Normal] \n", "\n", " widthavail_narrow widthavail_normal widthavail_wide widthavail_xwide \n", "0 0 1 1 0 \n", "1 0 1 0 0 \n", "2 0 1 0 0 \n", "3 0 1 0 0 \n", "4 0 1 0 0 \n", "\n", "[5 rows x 87 columns]" ] }, "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], "source": [ "wa_exploded = df[\"widthavail_list\"].explode()\n", "\n", "wa_ohe = (\n", " pd.crosstab(wa_exploded.index, wa_exploded)\n", " .reindex(df.index, fill_value=0)\n", ")\n", "\n", "wa_ohe = wa_ohe.rename(columns={\n", " \"Narrow\": \"widthavail_narrow\",\n", " \"Normal\": \"widthavail_normal\",\n", " \"Wide\": \"widthavail_wide\",\n", " \"X-Wide\": \"widthavail_xwide\"\n", "})\n", "\n", "for col in [\"widthavail_narrow\", \"widthavail_normal\", \"widthavail_wide\", \"widthavail_xwide\"]:\n", " if col not in wa_ohe.columns:\n", " wa_ohe[col] = 0\n", "\n", "wa_ohe = wa_ohe[[\"widthavail_narrow\",\"widthavail_normal\",\"widthavail_wide\",\"widthavail_xwide\"]]\n", "\n", "df = pd.concat([df, wa_ohe], axis=1)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 106, "id": "8ba40a97", "metadata": {}, "outputs": [], "source": [ "for c in [\"widthavail_narrow\",\"widthavail_normal\",\"widthavail_wide\",\"widthavail_xwide\"]:\n", " assert set(df[c].unique()).issubset({0, 1})" ] }, { "cell_type": "code", "execution_count": 107, "id": "0d75845f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "narrow sum: 93\n", "normal sum: 1170\n", "wide sum: 595\n", "xwide sum: 256\n", " Widths available widthavail_norm widthavail_normal widthavail_wide \\\n", "0 Normalwide Normal|Wide 1 1 \n", "7 Normalwide Normal|Wide 1 1 \n", "10 Normalwide Normal|Wide 1 1 \n", "11 Normalwide Normal|Wide 1 1 \n", "12 Normalwide Normal|Wide 1 1 \n", "13 Normalwide Normal|Wide 1 1 \n", "14 Normalwide Normal|Wide 1 1 \n", "15 Normalwide Normal|Wide 1 1 \n", "16 Normalwide Normal|Wide 1 1 \n", "17 Normalwide Normal|Wide 1 1 \n", "\n", " widthavail_xwide widthavail_narrow \n", "0 0 0 \n", "7 0 0 \n", "10 0 0 \n", "11 0 0 \n", "12 0 0 \n", "13 0 0 \n", "14 0 0 \n", "15 0 0 \n", "16 0 0 \n", "17 0 0 \n" ] } ], "source": [ "print(\"Rows:\", len(df))\n", "print(\"narrow sum:\", int(df[\"widthavail_narrow\"].sum()))\n", "print(\"normal sum:\", int(df[\"widthavail_normal\"].sum()))\n", "print(\"wide sum:\", int(df[\"widthavail_wide\"].sum()))\n", "print(\"xwide sum:\", int(df[\"widthavail_xwide\"].sum()))\n", "\n", "print(df[df[\"Widths available\"].isin([\"Normalwide\",\"Normalwidex-Wide\"])][\n", " [\"Widths available\",\"widthavail_norm\",\"widthavail_normal\",\"widthavail_wide\",\"widthavail_xwide\",\"widthavail_narrow\"]\n", "].head(10))" ] }, { "cell_type": "markdown", "id": "3a93dbbd", "metadata": {}, "source": [ "### Analisis Widths Available\n", "\n", "Widths available menjelaskan opsi lebar yang tersedia untuk model sepatu tersebut (bukan “fit feel”), misalnya hanya Normal, atau tersedia juga Wide dan X-Wide.\n", "\n", "Berbeda dengan Width / fit yang menggambarkan rasa lebar sepatu secara umum, Widths available itu varian produk yang dijual.\n", "\n", "Kategori yang relevan\n", "\n", "Narrow: opsi lebar sempit tersedia\n", "\n", "Normal: opsi standar tersedia\n", "\n", "Wide: opsi lebar tersedia\n", "\n", "X-Wide: opsi ekstra lebar tersedia" ] }, { "cell_type": "markdown", "id": "8c875704", "metadata": {}, "source": [ "# Cleaning Season" ] }, { "cell_type": "code", "execution_count": 109, "id": "cde921aa", "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 741\n", "Summerall Seasons 347\n", "- 63\n", "Winter 19\n", "Name: count, dtype: int64" ] }, "execution_count": 109, "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", "season_uniques = df[\"Season\"].dropna().unique()\n", "# season_uniques.sort()\n", "season_uniques = sorted(season_uniques)\n", "print(f\"Season ({len(season_uniques)} uniques): \\n\",season_uniques)\n", "\n", "df[\"Season\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 110, "id": "0e512dee", "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": 111, "id": "5652f560", "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": 112, "id": "5ec9108f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Season - norm: (4) uniques\n", " \n", "[nan, 'Summer|All', 'All', 'Winter']\n", "Length: 4, dtype: str\n", "season_norm\n", "All 741\n", "Summer|All 347\n", "Winter 19\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": 113, "id": "1face7ad", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...widthavail_listwidthavail_narrowwidthavail_normalwidthavail_widewidthavail_xwideseason_normseason_listseason_allseason_summerseason_winter
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...[Normal, Wide]0110NaNNaN000
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...[Normal]0100Summer|All[Summer, All]110
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...[Normal]0100All[All]100
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...[Normal]0100All[All]100
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...[Normal]0100All[All]100
\n", "

5 rows × 92 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... widthavail_list widthavail_narrow widthavail_normal \\\n", "0 Heelmid/Forefoot ... [Normal, Wide] 0 1 \n", "1 Mid/Forefoot ... [Normal] 0 1 \n", "2 Heelmid/Forefoot ... [Normal] 0 1 \n", "3 Heel ... [Normal] 0 1 \n", "4 Heelmid/Forefoot ... [Normal] 0 1 \n", "\n", " widthavail_wide widthavail_xwide season_norm season_list season_all \\\n", "0 1 0 NaN NaN 0 \n", "1 0 0 Summer|All [Summer, All] 1 \n", "2 0 0 All [All] 1 \n", "3 0 0 All [All] 1 \n", "4 0 0 All [All] 1 \n", "\n", " season_summer season_winter \n", "0 0 0 \n", "1 1 0 \n", "2 0 0 \n", "3 0 0 \n", "4 0 0 \n", "\n", "[5 rows x 92 columns]" ] }, "execution_count": 113, "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": "markdown", "id": "a18946b6", "metadata": {}, "source": [ "jujur janggal temen temen" ] }, { "cell_type": "code", "execution_count": 114, "id": "c1515be9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rows: 1170\n", "all seasons sum: 1088\n", "summer sum: 347\n", "winter sum: 19\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": 115, "id": "80f95641", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Season season_norm season_all season_summer season_winter\n", "1 Summerall Seasons Summer|All 1 1 0\n", "7 Summerall Seasons Summer|All 1 1 0\n", "9 Summerall Seasons Summer|All 1 1 0\n", "10 Summerall Seasons Summer|All 1 1 0\n", "11 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": "markdown", "id": "e8a94b15", "metadata": {}, "source": [ "# Split Weight lab Weight brand" ] }, { "cell_type": "code", "execution_count": 116, "id": "cf9c609f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(0)" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Cek \"-\" dan null\n", "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": 117, "id": "0ff4d1f0", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...widthavail_xwideseason_normseason_listseason_allseason_summerseason_winterweight_lab_ozweight_lab_gweight_brand_ozweight_brand_g
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...0NaNNaN0007.92258.1230.0
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...0Summer|All[Summer, All]11010.730410.9309.0
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0All[All]10011.933611.5327.0
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0All[All]10012.635612.4352.0
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0All[All]10012.334812.2345.0
\n", "

5 rows × 96 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... widthavail_xwide season_norm season_list \\\n", "0 Heelmid/Forefoot ... 0 NaN NaN \n", "1 Mid/Forefoot ... 0 Summer|All [Summer, All] \n", "2 Heelmid/Forefoot ... 0 All [All] \n", "3 Heel ... 0 All [All] \n", "4 Heelmid/Forefoot ... 0 All [All] \n", "\n", " season_all season_summer season_winter weight_lab_oz weight_lab_g \\\n", "0 0 0 0 7.9 225 \n", "1 1 1 0 10.7 304 \n", "2 1 0 0 11.9 336 \n", "3 1 0 0 12.6 356 \n", "4 1 0 0 12.3 348 \n", "\n", " weight_brand_oz weight_brand_g \n", "0 8.1 230.0 \n", "1 10.9 309.0 \n", "2 11.5 327.0 \n", "3 12.4 352.0 \n", "4 12.2 345.0 \n", "\n", "[5 rows x 96 columns]" ] }, "execution_count": 117, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ambil angka pakai regex\n", "weight = df[\"Weight lab Weight brand\"].str.findall(r\"[\\d.]+\")\n", "\n", "# Ubah jadi 4 kolom\n", "df[[\"weight_lab_oz\", \"weight_lab_g\", \"weight_brand_oz\", \"weight_brand_g\"]] = (\n", " pd.DataFrame(weight.tolist(), index=df.index)\n", ")\n", "\n", "# ubah ke numeric\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", "df.head()" ] }, { "cell_type": "markdown", "id": "ac8090cb", "metadata": {}, "source": [ "# Split Drop lab Drop Brand" ] }, { "cell_type": "code", "execution_count": 118, "id": "07739c09", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(0)" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Cek \"-\" dan null\n", "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": 119, "id": "3b2af74a", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...season_listseason_allseason_summerseason_winterweight_lab_ozweight_lab_gweight_brand_ozweight_brand_gdrop_lab_mmdrop_brand_mm
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...NaN0007.92258.1230.09.410.0
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...[Summer, All]11010.730410.9309.07.78.0
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...[All]10011.933611.5327.08.910.0
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...[All]10012.635612.4352.010.611.0
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...[All]10012.334812.2345.09.910.0
\n", "

5 rows × 98 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... season_list season_all season_summer \\\n", "0 Heelmid/Forefoot ... NaN 0 0 \n", "1 Mid/Forefoot ... [Summer, All] 1 1 \n", "2 Heelmid/Forefoot ... [All] 1 0 \n", "3 Heel ... [All] 1 0 \n", "4 Heelmid/Forefoot ... [All] 1 0 \n", "\n", " season_winter weight_lab_oz weight_lab_g weight_brand_oz weight_brand_g \\\n", "0 0 7.9 225 8.1 230.0 \n", "1 0 10.7 304 10.9 309.0 \n", "2 0 11.9 336 11.5 327.0 \n", "3 0 12.6 356 12.4 352.0 \n", "4 0 12.3 348 12.2 345.0 \n", "\n", " drop_lab_mm drop_brand_mm \n", "0 9.4 10.0 \n", "1 7.7 8.0 \n", "2 8.9 10.0 \n", "3 10.6 11.0 \n", "4 9.9 10.0 \n", "\n", "[5 rows x 98 columns]" ] }, "execution_count": 119, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ambil angka pakai regex\n", "drop = df[\"Drop lab Drop brand\"].str.findall(r\"[\\d.]+\")\n", "\n", "# Ubah jadi 2 kolom\n", "df[[\"drop_lab_mm\", \"drop_brand_mm\"]] = (\n", " pd.DataFrame(drop.tolist(), index=df.index)\n", ")\n", "\n", "# ubah ke numeric\n", "for col in [\"drop_lab_mm\", \"drop_brand_mm\"]:\n", " df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 120, "id": "4e164df8", "metadata": {}, "outputs": [], "source": [ "# df = df.drop(labels=\"drop_brand\", axis=1)\n", "# df = df.drop(labels=\"drop_lab\", axis=1)\n", "# df.head()" ] }, { "cell_type": "markdown", "id": "bda80a11", "metadata": {}, "source": [ "# Split Heel lab dan Heel brand" ] }, { "cell_type": "code", "execution_count": 121, "id": "27cb847d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(0)" ] }, "execution_count": 121, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Cek \"-\" dan null\n", "mask_missing = (\n", " df[\"Heel lab Heel brand\"].isna() |\n", " (df[\"Heel lab Heel brand\"].astype(str).str.strip() == \"-\")\n", ")\n", "mask_missing.sum()\n", "\n" ] }, { "cell_type": "code", "execution_count": 122, "id": "dacdb07a", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...season_summerseason_winterweight_lab_ozweight_lab_gweight_brand_ozweight_brand_gdrop_lab_mmdrop_brand_mmheel_lab_mmheel_brand_mm
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...007.92258.1230.09.410.032.436.0
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...1010.730410.9309.07.78.034.332.5
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...0011.933611.5327.08.910.033.332.5
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...0012.635612.4352.010.611.031.832.0
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...0012.334812.2345.09.910.032.634.0
\n", "

5 rows × 100 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... season_summer season_winter weight_lab_oz \\\n", "0 Heelmid/Forefoot ... 0 0 7.9 \n", "1 Mid/Forefoot ... 1 0 10.7 \n", "2 Heelmid/Forefoot ... 0 0 11.9 \n", "3 Heel ... 0 0 12.6 \n", "4 Heelmid/Forefoot ... 0 0 12.3 \n", "\n", " weight_lab_g weight_brand_oz weight_brand_g drop_lab_mm drop_brand_mm \\\n", "0 225 8.1 230.0 9.4 10.0 \n", "1 304 10.9 309.0 7.7 8.0 \n", "2 336 11.5 327.0 8.9 10.0 \n", "3 356 12.4 352.0 10.6 11.0 \n", "4 348 12.2 345.0 9.9 10.0 \n", "\n", " heel_lab_mm heel_brand_mm \n", "0 32.4 36.0 \n", "1 34.3 32.5 \n", "2 33.3 32.5 \n", "3 31.8 32.0 \n", "4 32.6 34.0 \n", "\n", "[5 rows x 100 columns]" ] }, "execution_count": 122, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ambil angka pakai regex\n", "Heel = df[\"Heel lab Heel brand\"].str.findall(r\"[\\d.]+\")\n", "\n", "# Ubah jadi 2 kolom\n", "df[[\"heel_lab_mm\", \"heel_brand_mm\"]] = (\n", " pd.DataFrame(Heel.tolist(), index=df.index)\n", ")\n", "\n", "# ubah ke numeric\n", "for col in [\"heel_lab_mm\", \"heel_brand_mm\"]:\n", " df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "df.head()" ] }, { "cell_type": "markdown", "id": "a5facbd7", "metadata": {}, "source": [ "# Split Forefoot lab dan Forefoot brand\n" ] }, { "cell_type": "code", "execution_count": 123, "id": "0fca0f24", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.int64(0)" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Cek \"-\" dan null\n", "mask_missing = (\n", " df[\"Forefoot lab Forefoot brand\"].isna() |\n", " (df[\"Forefoot lab Forefoot brand\"].astype(str).str.strip() == \"-\")\n", ")\n", "mask_missing.sum()\n" ] }, { "cell_type": "code", "execution_count": 124, "id": "dcd7f1b6", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...weight_lab_ozweight_lab_gweight_brand_ozweight_brand_gdrop_lab_mmdrop_brand_mmheel_lab_mmheel_brand_mmforefoot_lab_mmforefoot_brand_mm
0BrooksLaunch 987\\n Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...7.92258.1230.09.410.032.436.023.026.0
1BrooksLevitate 690\\n Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...10.730410.9309.07.78.034.332.526.624.5
2Adidas4DFWD90\\n Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...11.933611.5327.08.910.033.332.524.422.5
3Adidas4DFWD 290\\n Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...12.635612.4352.010.611.031.832.021.221.0
4Adidas4DFWD 388\\n Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...12.334812.2345.09.910.032.634.022.724.0
\n", "

5 rows × 102 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87\\n Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90\\n Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90\\n Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90\\n Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88\\n Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... weight_lab_oz weight_lab_g weight_brand_oz \\\n", "0 Heelmid/Forefoot ... 7.9 225 8.1 \n", "1 Mid/Forefoot ... 10.7 304 10.9 \n", "2 Heelmid/Forefoot ... 11.9 336 11.5 \n", "3 Heel ... 12.6 356 12.4 \n", "4 Heelmid/Forefoot ... 12.3 348 12.2 \n", "\n", " weight_brand_g drop_lab_mm drop_brand_mm heel_lab_mm heel_brand_mm \\\n", "0 230.0 9.4 10.0 32.4 36.0 \n", "1 309.0 7.7 8.0 34.3 32.5 \n", "2 327.0 8.9 10.0 33.3 32.5 \n", "3 352.0 10.6 11.0 31.8 32.0 \n", "4 345.0 9.9 10.0 32.6 34.0 \n", "\n", " forefoot_lab_mm forefoot_brand_mm \n", "0 23.0 26.0 \n", "1 26.6 24.5 \n", "2 24.4 22.5 \n", "3 21.2 21.0 \n", "4 22.7 24.0 \n", "\n", "[5 rows x 102 columns]" ] }, "execution_count": 124, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ambil angka pakai regex\n", "forefoot = df[\"Forefoot lab Forefoot brand\"].str.findall(r\"[\\d.]+\")\n", "\n", "# Ubah jadi 2 kolom\n", "df[[\"forefoot_lab_mm\", \"forefoot_brand_mm\"]] = (\n", " pd.DataFrame(forefoot.tolist(), index=df.index)\n", ")\n", "\n", "# ubah ke numeric\n", "for col in [\"forefoot_lab_mm\", \"forefoot_brand_mm\"]:\n", " df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n", "\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 125, "id": "7ccecc50", "metadata": {}, "outputs": [], "source": [ "df[\"Audience score\"] = (\n", " df[\"Audience score\"]\n", " .astype(str)\n", " .str.replace(\"\\n\", \" - \", regex=False)\n", " .str.strip()\n", ")\n" ] }, { "cell_type": "markdown", "id": "19dd690d", "metadata": {}, "source": [ "# Remove duplicates" ] }, { "cell_type": "markdown", "id": "c4f09526", "metadata": {}, "source": [ "cuma ada 433 shoes road" ] }, { "cell_type": "code", "execution_count": 126, "id": "7559acf1", "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", "
BrandName
5Adidas4DFWD 3
11AdidasAdistar 3
12AdidasAdistar 3
13AdidasAdistar 3
14AdidasAdistar 3
.........
163OnCloudflyer 5
164OnCloudflyer 5
166OnCloudgo
169OnCloudmonster 2
170OnCloudmonster 2
\n", "

100 rows × 2 columns

\n", "
" ], "text/plain": [ " Brand Name\n", "5 Adidas 4DFWD 3\n", "11 Adidas Adistar 3\n", "12 Adidas Adistar 3\n", "13 Adidas Adistar 3\n", "14 Adidas Adistar 3\n", ".. ... ...\n", "163 On Cloudflyer 5\n", "164 On Cloudflyer 5\n", "166 On Cloudgo\n", "169 On Cloudmonster 2\n", "170 On Cloudmonster 2\n", "\n", "[100 rows x 2 columns]" ] }, "execution_count": 126, "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": 127, "id": "4e91ab51", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before: 1170\n", "After : 434\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": 128, "id": "783d9c01", "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": 128, "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": "1873def0", "metadata": {}, "source": [ "udah ga ada duplicate, sisa 433 sepatu" ] }, { "cell_type": "markdown", "id": "a094cf88", "metadata": {}, "source": [ "# Done cleaned" ] }, { "cell_type": "code", "execution_count": 130, "id": "079b45bd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 434 entries, 0 to 433\n", "Columns: 102 entries, Brand to forefoot_brand_mm\n", "dtypes: float64(9), int64(55), object(4), str(34)\n", "memory usage: 346.0+ KB\n" ] } ], "source": [ "df.info()" ] }, { "cell_type": "markdown", "id": "813168be", "metadata": {}, "source": [ "kenapa ada int ya" ] }, { "cell_type": "code", "execution_count": 131, "id": "82f15329", "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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...weight_lab_ozweight_lab_gweight_brand_ozweight_brand_gdrop_lab_mmdrop_brand_mmheel_lab_mmheel_brand_mmforefoot_lab_mmforefoot_brand_mm
0BrooksLaunch 987 -  Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...7.92258.1230.09.410.032.436.023.026.0
1BrooksLevitate 690 -  Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...10.730410.9309.07.78.034.332.526.624.5
2Adidas4DFWD90 -  Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...11.933611.5327.08.910.033.332.524.422.5
3Adidas4DFWD 290 -  Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...12.635612.4352.010.611.031.832.021.221.0
4Adidas4DFWD 388 -  Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...12.334812.2345.09.910.032.634.022.724.0
\n", "

5 rows × 102 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price Pace Arch support \\\n", "0 Brooks Launch 9 87 - Great! $110 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 90 - Superb! $150 Daily Running Neutral \n", "2 Adidas 4DFWD 90 - Superb! $200 Daily Running Neutral \n", "3 Adidas 4DFWD 2 90 - Superb! $200 Daily Running Neutral \n", "4 Adidas 4DFWD 3 88 - Great! $200 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern ... weight_lab_oz weight_lab_g weight_brand_oz \\\n", "0 Heelmid/Forefoot ... 7.9 225 8.1 \n", "1 Mid/Forefoot ... 10.7 304 10.9 \n", "2 Heelmid/Forefoot ... 11.9 336 11.5 \n", "3 Heel ... 12.6 356 12.4 \n", "4 Heelmid/Forefoot ... 12.3 348 12.2 \n", "\n", " weight_brand_g drop_lab_mm drop_brand_mm heel_lab_mm heel_brand_mm \\\n", "0 230.0 9.4 10.0 32.4 36.0 \n", "1 309.0 7.7 8.0 34.3 32.5 \n", "2 327.0 8.9 10.0 33.3 32.5 \n", "3 352.0 10.6 11.0 31.8 32.0 \n", "4 345.0 9.9 10.0 32.6 34.0 \n", "\n", " forefoot_lab_mm forefoot_brand_mm \n", "0 23.0 26.0 \n", "1 26.6 24.5 \n", "2 24.4 22.5 \n", "3 21.2 21.0 \n", "4 22.7 24.0 \n", "\n", "[5 rows x 102 columns]" ] }, "execution_count": 131, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 132, "id": "2832aee5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Weight lab Weight brand weight_lab_oz weight_lab_g \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 7.9 225 \n", "1 10.7 oz / 304g 10.9 oz / 309g 10.7 304 \n", "2 11.9 oz / 336g 11.5 oz / 327g 11.9 336 \n", "3 12.6 oz / 356g 12.4 oz / 352g 12.6 356 \n", "4 12.3 oz / 348g 12.2 oz / 345g 12.3 348 \n", ".. ... ... ... \n", "429 9.8 oz / 279g 10.1 oz / 286g 9.8 279 \n", "430 8.7 oz / 248g 8.6 oz / 244g 8.7 248 \n", "431 10.3 oz / 291g 9.7 oz / 274g 10.3 291 \n", "432 6 oz / 171g 6 oz / 171g 6.0 171 \n", "433 6.9 oz / 196g 6.9 oz / 196g 6.9 196 \n", "\n", " weight_brand_oz weight_brand_g \n", "0 8.1 230.0 \n", "1 10.9 309.0 \n", "2 11.5 327.0 \n", "3 12.4 352.0 \n", "4 12.2 345.0 \n", ".. ... ... \n", "429 10.1 286.0 \n", "430 8.6 244.0 \n", "431 9.7 274.0 \n", "432 6.0 171.0 \n", "433 6.9 196.0 \n", "\n", "[434 rows x 5 columns]\n" ] } ], "source": [ "print(df[['Weight lab Weight brand', 'weight_lab_oz', 'weight_lab_g', 'weight_brand_oz',\t'weight_brand_g']])" ] }, { "cell_type": "code", "execution_count": 133, "id": "9266754f", "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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 scorePricePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike pattern...weight_lab_ozweight_lab_gweight_brand_ozweight_brand_gdrop_lab_mmdrop_brand_mmheel_lab_mmheel_brand_mmforefoot_lab_mmforefoot_brand_mm
0BrooksLaunch 987 -  Great!$110Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/Forefoot...7.92258.1230.09.410.032.436.023.026.0
1BrooksLevitate 690 -  Superb!$150Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/Forefoot...10.730410.9309.07.78.034.332.526.624.5
2Adidas4DFWD90 -  Superb!$200Daily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/Forefoot...11.933611.5327.08.910.033.332.524.422.5
3Adidas4DFWD 290 -  Superb!$200Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeel...12.635612.4352.010.611.031.832.021.221.0
4Adidas4DFWD 388 -  Great!$200Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/Forefoot...12.334812.2345.09.910.032.634.022.724.0
..................................................................
428NikeZoom Fly 486 -  Good!$160TempoNeutral9.6 oz / 271g 8.8 oz / 249g07.1 mm 8.0 mmMid/Forefoot...9.62718.8249.07.18.038.436.031.3NaN
429NikeZoom Fly 580 -  Good!$160Daily RunningtempoNeutral9.8 oz / 279g 10.1 oz / 286g07.5 mm 8.0 mmMid/Forefoot...9.827910.1286.07.58.036.941.029.433.0
430NikeZoom Fly 692 -  Superb!$170CompetitiontempoNeutral8.7 oz / 248g 8.6 oz / 244g19.6 mm 8.0 mmHeelmid/Forefoot...8.72488.6244.09.68.039.740.030.132.0
431NikeZoomX Invincible Run Flyknit 286 -  Good!$180Daily RunningNeutral10.3 oz / 291g 9.7 oz / 274g012.0 mm 9.0 mmHeel...10.32919.7274.012.09.035.537.023.528.0
432NikeZoomX Streakfly87 -  Great!$160TempoNeutral6 oz / 171g 6 oz / 171g16.3 mm 6.0 mmMid/Forefoot...6.01716.0171.06.36.031.732.025.426.0
\n", "

433 rows × 102 columns

\n", "
" ], "text/plain": [ " Brand Name Audience score Price \\\n", "0 Brooks Launch 9 87 - Great! $110 \n", "1 Brooks Levitate 6 90 - Superb! $150 \n", "2 Adidas 4DFWD 90 - Superb! $200 \n", "3 Adidas 4DFWD 2 90 - Superb! $200 \n", "4 Adidas 4DFWD 3 88 - Great! $200 \n", ".. ... ... ... ... \n", "428 Nike Zoom Fly 4 86 - Good! $160 \n", "429 Nike Zoom Fly 5 80 - Good! $160 \n", "430 Nike Zoom Fly 6 92 - Superb! $170 \n", "431 Nike ZoomX Invincible Run Flyknit 2 86 - Good! $180 \n", "432 Nike ZoomX Streakfly 87 - Great! $160 \n", "\n", " Pace Arch support Weight lab Weight brand \\\n", "0 Daily Runningtempo Neutral 7.9 oz / 225g 8.1 oz / 230g \n", "1 Daily Running Neutral 10.7 oz / 304g 10.9 oz / 309g \n", "2 Daily Running Neutral 11.9 oz / 336g 11.5 oz / 327g \n", "3 Daily Running Neutral 12.6 oz / 356g 12.4 oz / 352g \n", "4 Daily Running Neutral 12.3 oz / 348g 12.2 oz / 345g \n", ".. ... ... ... \n", "428 Tempo Neutral 9.6 oz / 271g 8.8 oz / 249g \n", "429 Daily Runningtempo Neutral 9.8 oz / 279g 10.1 oz / 286g \n", "430 Competitiontempo Neutral 8.7 oz / 248g 8.6 oz / 244g \n", "431 Daily Running Neutral 10.3 oz / 291g 9.7 oz / 274g \n", "432 Tempo Neutral 6 oz / 171g 6 oz / 171g \n", "\n", " Lightweight Drop lab Drop brand Strike pattern ... weight_lab_oz \\\n", "0 1 9.4 mm 10.0 mm Heelmid/Forefoot ... 7.9 \n", "1 0 7.7 mm 8.0 mm Mid/Forefoot ... 10.7 \n", "2 0 8.9 mm 10.0 mm Heelmid/Forefoot ... 11.9 \n", "3 0 10.6 mm 11.0 mm Heel ... 12.6 \n", "4 0 9.9 mm 10.0 mm Heelmid/Forefoot ... 12.3 \n", ".. ... ... ... ... ... \n", "428 0 7.1 mm 8.0 mm Mid/Forefoot ... 9.6 \n", "429 0 7.5 mm 8.0 mm Mid/Forefoot ... 9.8 \n", "430 1 9.6 mm 8.0 mm Heelmid/Forefoot ... 8.7 \n", "431 0 12.0 mm 9.0 mm Heel ... 10.3 \n", "432 1 6.3 mm 6.0 mm Mid/Forefoot ... 6.0 \n", "\n", " weight_lab_g weight_brand_oz weight_brand_g drop_lab_mm drop_brand_mm \\\n", "0 225 8.1 230.0 9.4 10.0 \n", "1 304 10.9 309.0 7.7 8.0 \n", "2 336 11.5 327.0 8.9 10.0 \n", "3 356 12.4 352.0 10.6 11.0 \n", "4 348 12.2 345.0 9.9 10.0 \n", ".. ... ... ... ... ... \n", "428 271 8.8 249.0 7.1 8.0 \n", "429 279 10.1 286.0 7.5 8.0 \n", "430 248 8.6 244.0 9.6 8.0 \n", "431 291 9.7 274.0 12.0 9.0 \n", "432 171 6.0 171.0 6.3 6.0 \n", "\n", " heel_lab_mm heel_brand_mm forefoot_lab_mm forefoot_brand_mm \n", "0 32.4 36.0 23.0 26.0 \n", "1 34.3 32.5 26.6 24.5 \n", "2 33.3 32.5 24.4 22.5 \n", "3 31.8 32.0 21.2 21.0 \n", "4 32.6 34.0 22.7 24.0 \n", ".. ... ... ... ... \n", "428 38.4 36.0 31.3 NaN \n", "429 36.9 41.0 29.4 33.0 \n", "430 39.7 40.0 30.1 32.0 \n", "431 35.5 37.0 23.5 28.0 \n", "432 31.7 32.0 25.4 26.0 \n", "\n", "[433 rows x 102 columns]" ] }, "execution_count": 133, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head(433)" ] }, { "cell_type": "code", "execution_count": 138, "id": "6a9ceda0", "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", "
BrandNamePaceArch supportWeight lab Weight brandLightweightDrop lab Drop brandStrike patternSizeMidsole softness...weight_lab_ozweight_lab_gweight_brand_ozweight_brand_gdrop_lab_mmdrop_brand_mmheel_lab_mmheel_brand_mmforefoot_lab_mmforefoot_brand_mm
0BrooksLaunch 9Daily RunningtempoNeutral7.9 oz / 225g 8.1 oz / 230g19.4 mm 10.0 mmHeelmid/ForefootTrue To SizeBalanced...7.92258.1230.09.410.032.436.023.026.0
1BrooksLevitate 6Daily RunningNeutral10.7 oz / 304g 10.9 oz / 309g07.7 mm 8.0 mmMid/ForefootTrue To SizeSoft...10.730410.9309.07.78.034.332.526.624.5
2Adidas4DFWDDaily RunningNeutral11.9 oz / 336g 11.5 oz / 327g08.9 mm 10.0 mmHeelmid/ForefootTrue To SizeFirm...11.933611.5327.08.910.033.332.524.422.5
3Adidas4DFWD 2Daily RunningNeutral12.6 oz / 356g 12.4 oz / 352g010.6 mm 11.0 mmHeelSlightly SmallFirm...12.635612.4352.010.611.031.832.021.221.0
4Adidas4DFWD 3Daily RunningNeutral12.3 oz / 348g 12.2 oz / 345g09.9 mm 10.0 mmHeelmid/ForefootTrue To SizeFirm...12.334812.2345.09.910.032.634.022.724.0
\n", "

5 rows × 100 columns

\n", "
" ], "text/plain": [ " Brand Name Pace Arch support \\\n", "0 Brooks Launch 9 Daily Runningtempo Neutral \n", "1 Brooks Levitate 6 Daily Running Neutral \n", "2 Adidas 4DFWD Daily Running Neutral \n", "3 Adidas 4DFWD 2 Daily Running Neutral \n", "4 Adidas 4DFWD 3 Daily Running Neutral \n", "\n", " Weight lab Weight brand Lightweight Drop lab Drop brand \\\n", "0 7.9 oz / 225g 8.1 oz / 230g 1 9.4 mm 10.0 mm \n", "1 10.7 oz / 304g 10.9 oz / 309g 0 7.7 mm 8.0 mm \n", "2 11.9 oz / 336g 11.5 oz / 327g 0 8.9 mm 10.0 mm \n", "3 12.6 oz / 356g 12.4 oz / 352g 0 10.6 mm 11.0 mm \n", "4 12.3 oz / 348g 12.2 oz / 345g 0 9.9 mm 10.0 mm \n", "\n", " Strike pattern Size Midsole softness ... weight_lab_oz \\\n", "0 Heelmid/Forefoot True To Size Balanced ... 7.9 \n", "1 Mid/Forefoot True To Size Soft ... 10.7 \n", "2 Heelmid/Forefoot True To Size Firm ... 11.9 \n", "3 Heel Slightly Small Firm ... 12.6 \n", "4 Heelmid/Forefoot True To Size Firm ... 12.3 \n", "\n", " weight_lab_g weight_brand_oz weight_brand_g drop_lab_mm drop_brand_mm \\\n", "0 225 8.1 230.0 9.4 10.0 \n", "1 304 10.9 309.0 7.7 8.0 \n", "2 336 11.5 327.0 8.9 10.0 \n", "3 356 12.4 352.0 10.6 11.0 \n", "4 348 12.2 345.0 9.9 10.0 \n", "\n", " heel_lab_mm heel_brand_mm forefoot_lab_mm forefoot_brand_mm \n", "0 32.4 36.0 23.0 26.0 \n", "1 34.3 32.5 26.6 24.5 \n", "2 33.3 32.5 24.4 22.5 \n", "3 31.8 32.0 21.2 21.0 \n", "4 32.6 34.0 22.7 24.0 \n", "\n", "[5 rows x 100 columns]" ] }, "execution_count": 138, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.drop(columns=[\"Audience score\", \"Price\"], inplace=True)\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 139, "id": "154d8336", "metadata": {}, "outputs": [], "source": [ "df.to_csv('../../data/road_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 }