{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b0b86d33",
   "metadata": {},
   "source": [
    "# 04 · Feature engineering\n",
    "\n",
    "**Feature engineering** = creating new columns that make the pattern easier for the model to see.\n",
    "Ideas come from the EDA hypotheses and from common sense about houses.\n",
    "\n",
    "We work like scientists: **change one thing → re-run CV → keep it only if CV improves.** Every experiment goes into a log.\n",
    "The model stays fixed (the same Random Forest), so only the features change."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "86abb818",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:01.304319Z",
     "iopub.status.busy": "2026-10-23T06:12:01.304319Z",
     "iopub.status.idle": "2026-10-23T06:12:06.317639Z",
     "shell.execute_reply": "2026-10-23T06:12:06.317639Z"
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from utils import (load_data, basic_prep, add_features, add_target_encoding, cv_score,\n",
    "                   save_submission, TARGET, TIER_TO_NUM, LAYOUT_KEYS, SEED)\n",
    "from score import score\n",
    "\n",
    "train, test = load_data()\n",
    "tr, te = basic_prep(train, test)\n",
    "full, te_full = add_features(tr), add_features(te)\n",
    "y = tr[TARGET].map(TIER_TO_NUM)\n",
    "BASE = [c for c in tr.columns if c not in (\"id\", TARGET)]\n",
    "\n",
    "def rf():\n",
    "    return RandomForestClassifier(n_estimators=300, random_state=SEED, n_jobs=-1)\n",
    "\n",
    "log = []  # our experiment log\n",
    "def experiment(name, X, **kw):\n",
    "    mean, std, _ = cv_score(rf, X, y, verbose=False, **kw)\n",
    "    log.append({\"experiment\": name, \"n_features\": X.shape[1], \"cv_acc\": round(mean, 4), \"std\": round(std, 4)})\n",
    "    print(f\"{name:38s} CV = {mean:.4f} ± {std:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e1666d16",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:06.317639Z",
     "iopub.status.busy": "2026-10-23T06:12:06.317639Z",
     "iopub.status.idle": "2026-10-23T06:12:14.514233Z",
     "shell.execute_reply": "2026-10-23T06:12:14.514233Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0. baseline (raw columns)              CV = 0.6961 ± 0.0303\n"
     ]
    }
   ],
   "source": [
    "experiment(\"0. baseline (raw columns)\", tr[BASE])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91366c19",
   "metadata": {},
   "source": [
    "The new columns (all in `add_features()` in `utils.py`):\n",
    "- `amenities`: how many of the 6 yes/no boxes are \"yes\" (one \"how fancy is it\" score),\n",
    "- `total_rooms` = bedrooms + bathrooms,\n",
    "- `area_per_room`: how spacious the rooms are,\n",
    "- `bath_per_bed`: 1 bathroom for 4 bedrooms feels cheaper than 2 for 2,\n",
    "- `log_area`: area on a log scale."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "399e7681",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:14.517983Z",
     "iopub.status.busy": "2026-10-23T06:12:14.516222Z",
     "iopub.status.idle": "2026-10-23T06:12:14.544253Z",
     "shell.execute_reply": "2026-10-23T06:12:14.542704Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>amenities</th>\n",
       "      <td>408.0</td>\n",
       "      <td>1.98</td>\n",
       "      <td>1.17</td>\n",
       "      <td>0.00</td>\n",
       "      <td>1.00</td>\n",
       "      <td>2.00</td>\n",
       "      <td>3.00</td>\n",
       "      <td>5.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>total_rooms</th>\n",
       "      <td>408.0</td>\n",
       "      <td>4.23</td>\n",
       "      <td>1.01</td>\n",
       "      <td>2.00</td>\n",
       "      <td>4.00</td>\n",
       "      <td>4.00</td>\n",
       "      <td>5.00</td>\n",
       "      <td>8.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>area_per_room</th>\n",
       "      <td>408.0</td>\n",
       "      <td>1246.22</td>\n",
       "      <td>560.67</td>\n",
       "      <td>317.50</td>\n",
       "      <td>898.67</td>\n",
       "      <td>1132.86</td>\n",
       "      <td>1488.50</td>\n",
       "      <td>4400.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>bath_per_bed</th>\n",
       "      <td>408.0</td>\n",
       "      <td>0.45</td>\n",
       "      <td>0.16</td>\n",
       "      <td>0.20</td>\n",
       "      <td>0.33</td>\n",
       "      <td>0.37</td>\n",
       "      <td>0.50</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>log_area</th>\n",
       "      <td>408.0</td>\n",
       "      <td>8.46</td>\n",
       "      <td>0.39</td>\n",
       "      <td>7.41</td>\n",
       "      <td>8.18</td>\n",
       "      <td>8.41</td>\n",
       "      <td>8.76</td>\n",
       "      <td>9.66</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               count     mean     std     min     25%      50%      75%  \\\n",
       "amenities      408.0     1.98    1.17    0.00    1.00     2.00     3.00   \n",
       "total_rooms    408.0     4.23    1.01    2.00    4.00     4.00     5.00   \n",
       "area_per_room  408.0  1246.22  560.67  317.50  898.67  1132.86  1488.50   \n",
       "bath_per_bed   408.0     0.45    0.16    0.20    0.33     0.37     0.50   \n",
       "log_area       408.0     8.46    0.39    7.41    8.18     8.41     8.76   \n",
       "\n",
       "                   max  \n",
       "amenities         5.00  \n",
       "total_rooms       8.00  \n",
       "area_per_room  4400.00  \n",
       "bath_per_bed      1.00  \n",
       "log_area          9.66  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "full[[\"amenities\", \"total_rooms\", \"area_per_room\", \"bath_per_bed\", \"log_area\"]].describe().T.round(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bc9140f",
   "metadata": {},
   "source": [
    "## Idea 1: amenities count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a1ba107c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:14.547317Z",
     "iopub.status.busy": "2026-10-23T06:12:14.545792Z",
     "iopub.status.idle": "2026-10-23T06:12:22.714194Z",
     "shell.execute_reply": "2026-10-23T06:12:22.714194Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. + amenities                         CV = 0.7001 ± 0.0309\n"
     ]
    }
   ],
   "source": [
    "experiment(\"1. + amenities\", full[BASE + [\"amenities\"]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f998f54c",
   "metadata": {},
   "source": [
    "## Idea 2: room ratios"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "635893b3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:22.714194Z",
     "iopub.status.busy": "2026-10-23T06:12:22.714194Z",
     "iopub.status.idle": "2026-10-23T06:12:30.857904Z",
     "shell.execute_reply": "2026-10-23T06:12:30.857904Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2. + total_rooms, area_per_room, bath_per_bed CV = 0.6887 ± 0.0385\n"
     ]
    }
   ],
   "source": [
    "experiment(\"2. + total_rooms, area_per_room, bath_per_bed\", full[BASE + [\"total_rooms\", \"area_per_room\", \"bath_per_bed\"]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67fac4eb",
   "metadata": {},
   "source": [
    "## Idea 3: log of area\n",
    "Trees only care about the **order** of values (\"is area bigger than X?\"), and taking the log doesn't change the order.\n",
    "So this should do **nothing** for a Random Forest. Let's confirm. (It *can* help linear models like Logistic Regression; we re-test it in 05.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6467f571",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:30.862015Z",
     "iopub.status.busy": "2026-10-23T06:12:30.860394Z",
     "iopub.status.idle": "2026-10-23T06:12:39.107255Z",
     "shell.execute_reply": "2026-10-23T06:12:39.107255Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3. + log_area                          CV = 0.6961 ± 0.0331\n"
     ]
    }
   ],
   "source": [
    "experiment(\"3. + log_area\", full[BASE + [\"log_area\"]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ce03435",
   "metadata": {},
   "source": [
    "Exactly the same score as the baseline: confirmed.\n",
    "\n",
    "**Now read ideas 1–2 carefully.** The changes are small (under 1%), and on ~400 rows CV moves by about ±0.8% from noise alone (the `std` divided by √15, the number of folds).\n",
    "**Neither difference is clearly bigger than the noise.** That's a real and common outcome: the raw columns already describe the houses well."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "016a7e7f",
   "metadata": {},
   "source": [
    "## Idea 4: \"same description\" price (target encoding), and the leakage trap ⚠️\n",
    "Idea: houses with the **same description** (same bedrooms, bathrooms, stories, parking, furnishing, AC and preferred area) probably sell in a similar range.\n",
    "So for each house, compute the **average tier of houses with the same description**.\n",
    "\n",
    "This uses the **target** to build a feature, which is dangerous. Let's do it the **wrong way** first.\n",
    "\n",
    "### Wrong way: compute the averages on all of train, then run CV"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ee4ed663",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:39.111533Z",
     "iopub.status.busy": "2026-10-23T06:12:39.110074Z",
     "iopub.status.idle": "2026-10-23T06:12:48.031697Z",
     "shell.execute_reply": "2026-10-23T06:12:48.029688Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "different descriptions: 210 | houses per description (median): 1.0\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4a. + layout_price (LEAKY)             CV = 0.7998 ± 0.0307\n"
     ]
    }
   ],
   "source": [
    "keys = list(LAYOUT_KEYS)\n",
    "layout = tr[keys].astype(str).agg(\"_\".join, axis=1)\n",
    "print(\"different descriptions:\", layout.nunique(), \"| houses per description (median):\", layout.value_counts().median())\n",
    "leaky = tr[BASE].assign(layout_price=y.groupby(layout).transform(\"mean\"))\n",
    "experiment(\"4a. + layout_price (LEAKY)\", leaky)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78ce7637",
   "metadata": {},
   "source": [
    "A **huge** jump, about 10 points! Too good to be true? Check the leaderboard. For test houses we can only use train's averages, which is exactly the situation the model will face for real:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c63f4774",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:48.034715Z",
     "iopub.status.busy": "2026-10-23T06:12:48.034715Z",
     "iopub.status.idle": "2026-10-23T06:12:48.721619Z",
     "shell.execute_reply": "2026-10-23T06:12:48.721619Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "leaderboard: {'public': 0.5323}\n"
     ]
    }
   ],
   "source": [
    "layout_means = y.groupby(layout).mean()\n",
    "te_layout = te[keys].astype(str).agg(\"_\".join, axis=1)\n",
    "te_leaky = te[BASE].assign(layout_price=te_layout.map(layout_means).fillna(y.mean()))\n",
    "m = rf().fit(leaky, y)\n",
    "print(\"leaderboard:\", score(save_submission(te, m.predict(te_leaky), \"04_leaky_target_encoding\")))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5fea026",
   "metadata": {},
   "source": [
    "**CV says ~0.80, but the leaderboard collapses to worse than our first Random Forest.** Why?\n",
    "Most descriptions occur only **once** in train (median = 1 house). Each house's `layout_price` was computed *including its own answer*, so for most houses `layout_price` **is** the answer.\n",
    "The model learned \"just copy layout_price\". On test houses that shortcut doesn't exist (most of their descriptions were never seen), so the model is lost.\n",
    "\n",
    "This is **data leakage**: information about the answer sneaking into the features. It is the #1 way people fool themselves, and it's why \"too good to be true\" CV jumps deserve suspicion.\n",
    "\n",
    "### Right way: learn the averages inside each fold, from the training part only\n",
    "`add_target_encoding()` in `utils.py` does it properly:\n",
    "- validation/test rows get averages computed only from the training fold,\n",
    "- training rows get a *leave-one-out* average (their own answer removed),\n",
    "- small groups are pulled towards the overall average (**smoothing**), so a description seen twice doesn't get an extreme value.\n",
    "\n",
    "`cv_score(..., fold_fn=add_target_encoding)` runs it separately inside every fold. (The log shows one feature fewer because `layout_price` is added inside each fold.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9bed50f1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:48.721619Z",
     "iopub.status.busy": "2026-10-23T06:12:48.721619Z",
     "iopub.status.idle": "2026-10-23T06:12:58.680909Z",
     "shell.execute_reply": "2026-10-23T06:12:58.679519Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4b. + layout_price (correct, in-fold)  CV = 0.7001 ± 0.0330\n"
     ]
    }
   ],
   "source": [
    "experiment(\"4b. + layout_price (correct, in-fold)\", tr[BASE], fold_fn=add_target_encoding)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a82c6785",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:58.682421Z",
     "iopub.status.busy": "2026-10-23T06:12:58.682421Z",
     "iopub.status.idle": "2026-10-23T06:12:59.318915Z",
     "shell.execute_reply": "2026-10-23T06:12:59.318915Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "leaderboard: {'public': 0.7258}\n"
     ]
    }
   ],
   "source": [
    "X_fit, X_te = add_target_encoding(tr[BASE], y, te[BASE])\n",
    "m = rf().fit(X_fit, y)\n",
    "print(\"leaderboard:\", score(save_submission(te, m.predict(X_te), \"04_features_te\")))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15f2b54f",
   "metadata": {},
   "source": [
    "Done honestly, the \"magic\" disappears: CV goes back to roughly the baseline. The feature carried no real extra information, only the leaked answer."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0793522d",
   "metadata": {},
   "source": [
    "## Experiment log"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0f8af160",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:59.322471Z",
     "iopub.status.busy": "2026-10-23T06:12:59.322471Z",
     "iopub.status.idle": "2026-10-23T06:12:59.337998Z",
     "shell.execute_reply": "2026-10-23T06:12:59.336467Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>experiment</th>\n",
       "      <th>n_features</th>\n",
       "      <th>cv_acc</th>\n",
       "      <th>std</th>\n",
       "      <th>vs_baseline</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0. baseline (raw columns)</td>\n",
       "      <td>12</td>\n",
       "      <td>0.6961</td>\n",
       "      <td>0.0303</td>\n",
       "      <td>0.0000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1. + amenities</td>\n",
       "      <td>13</td>\n",
       "      <td>0.7001</td>\n",
       "      <td>0.0309</td>\n",
       "      <td>0.0040</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2. + total_rooms, area_per_room, bath_per_bed</td>\n",
       "      <td>15</td>\n",
       "      <td>0.6887</td>\n",
       "      <td>0.0385</td>\n",
       "      <td>-0.0074</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3. + log_area</td>\n",
       "      <td>13</td>\n",
       "      <td>0.6961</td>\n",
       "      <td>0.0331</td>\n",
       "      <td>0.0000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4a. + layout_price (LEAKY)</td>\n",
       "      <td>13</td>\n",
       "      <td>0.7998</td>\n",
       "      <td>0.0307</td>\n",
       "      <td>0.1037</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>4b. + layout_price (correct, in-fold)</td>\n",
       "      <td>12</td>\n",
       "      <td>0.7001</td>\n",
       "      <td>0.0330</td>\n",
       "      <td>0.0040</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                      experiment  n_features  cv_acc     std  \\\n",
       "0                      0. baseline (raw columns)          12  0.6961  0.0303   \n",
       "1                                 1. + amenities          13  0.7001  0.0309   \n",
       "2  2. + total_rooms, area_per_room, bath_per_bed          15  0.6887  0.0385   \n",
       "3                                  3. + log_area          13  0.6961  0.0331   \n",
       "4                     4a. + layout_price (LEAKY)          13  0.7998  0.0307   \n",
       "5          4b. + layout_price (correct, in-fold)          12  0.7001  0.0330   \n",
       "\n",
       "   vs_baseline  \n",
       "0       0.0000  \n",
       "1       0.0040  \n",
       "2      -0.0074  \n",
       "3       0.0000  \n",
       "4       0.1037  \n",
       "5       0.0040  "
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "log_df = pd.DataFrame(log)\n",
    "log_df[\"vs_baseline\"] = (log_df.cv_acc - log_df.cv_acc[0]).round(4)\n",
    "log_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e01fd16a",
   "metadata": {},
   "source": [
    "## What does the model rely on?\n",
    "A Random Forest can report how much each feature helped its splits (**feature importance**):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "68ef9956",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-23T06:12:59.337998Z",
     "iopub.status.busy": "2026-10-23T06:12:59.337998Z",
     "iopub.status.idle": "2026-10-23T06:13:00.893362Z",
     "shell.execute_reply": "2026-10-23T06:13:00.893362Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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KlKkiPktxP7222+WNWtW16Mb3zRaSf0tCAAAIDkkNHsQYHHBHyIAAIBLmT2YRgsAAAC+QoAFAACArxBgAQAA4CsEWAAAAPgKARYAAAC+QoAFAACArxBgAQAA4CsEWAAAAPgKARYAAAC+QoAFAACArxBgAQAA4CsEWAAAAPgKARYAAAC+QoAFAACAr2RM6RNA6ld98AyLjMqW0qeR5kUPa5fSpwAAgC9QgQUAAICvUIG9hFasWGFffvml7dmzx/r162eVKlW6lIcHAABIE6jAXiKbN2+2OnXq2M6dO6106dKWNWvWS3VoAACANIUK7CXy008/Wf78+e3NN9+8VIcEAABIkwiw/2fx4sX29ddfW//+/d1tflVMGzRoYB06dDhnnXvvvdc+/fRT++eff+zJJ5+0fPny2f79+23cuHG2ceNGV2G98cYbrUCBAm678ePH2/vvv2+HDh2yAQMGWI4cOez555+3qVOn2uzZs906efPmdRXadu3CB/J8+OGHlj17ditbtqxbX9s+8sgj7rWVK1faV199ZUePHrWaNWtaly5dLDLy/xfVhw4dajt27HDLihUrZm3btrXq1atf/E8VAADARUQLwf9RGBw+fLjVq1fPVq9ebWfOnLFbbrnFBg0adM46DRs2tC1btljJkiUtY8aMtmrVKqtWrZoLo7lz57Z58+bZZZdd5paLKq96ZMqUycqUKeO280Krnutx6tQpF57vvPPOsB+QQqsC6x133GERERFWtGhRt3zMmDHuPLZt22ZRUVH20ksvWYsWLdx5e4oXL+72XaJECVu3bp3Vr1/fhXMAAAA/iwgEAoGUPonUQBXVW2+91T766CO77bbb3LLp06dbx44dXaBVBdRbR8tVzfQ0adLEhUlVPD19+/Z1/a5eYHz33Xdd+FWQjItCsQLn8uXLrXLlym5Z165d7ccff7T169dbzpw53TKFVp3P3Llz7eqrr3bLjh8/blWqVLFnn302eP4xjRw50v7zn/+4wWSxOXHihHt4Dh486MJ2yQETmEbrEmAaLQBAenfw4EFXDDxw4IDlypUrzvVoIQihW+033XRT8Pm1117rLp4CpAKjqNrZpk2b4Dp79+51/a26Ra9KqX4f0GPDhg2uYns+P//8s3so7J49e9btXwHTC7DStGnTYHiV7777zn2dNGmSTZw40X2vY6oa/NtvvwUD7MmTJ12A1nnoA6Hgu2bNGlftVTU4JgXwIUOGnPecAQAAUhIBNoTCaubMmcMuUMGCBV0fqSdPnjzuVr5n165d7qsqlbpl7ylVqpR16tQp3ouvwPvxxx+70Kzb/Dq2Qqh+6wilHttQCrvZsmVz24RSb65aF+TIkSOuh1ehXH21Oj+dt1oM9JreR0xql3jooYfOqcACAACkJgTYEAqOCncaNCWqiKpqGRpMYypcuLALhrVr1w6r3p6PqqC6na9BYV5FV8seffTR826rPliFy7vuussN6orN999/b5s2bbLt27e7qq5MnjzZRowYEed+tZ63LgAAQGrFIK4Qug2vXlWPel51G16Do+KiSqb6YYcNG+ZmGfBoZgAN5oqLwrGqoadPnw4u0xRboc/jct1117kK7ODBg8OWq21B/bpeGNb78QZ1eYEZAADA76jAhlA1U6P71dOq2/mqjmp0f5EiReK9iKNHj7b27dtb1apVrWXLlnb48GH7/fff3S35a665JtZtVOnUX+PSoLAbbrjBtm7d6npV42tY9mh6Lk3N1aNHD3euV1xxhUVHR7tBYBMmTHDrKFSrUqtZFTT7wPz588Om2AIAAPArAmwItQ4sWrTI5syZ4+aBfeKJJ1w49Gie1ueee+6ci6gBXBo8pYqrps5SW8E777zj+mc9mqUgS5YsYdup4qq5WzVoq1ChQi50fv7551a3bt3gOpo+K7a/2qUBZgqtmrpLfbjdu3d3syF4g7P0XpYsWeKm4dq9e7ebEkyzFGiuWv4KGAAA8DOm0QppF9CgKvWMInwqC6bRujSYRgsAkN4dTOA0WtxTBgAAgK/QQnCe9gCYLRvSJkG9uQAAAJcCAfb/qD9UDwAAAKRutBAAAADAVwiwAAAA8BUCLAAAAHyFAAsAAABfIcACAADAVwiwAAAA8BUCLAAAAHyFAAsAAABfIcACAADAVwiwAAAA8BUCLAAAAHyFAAsAAABfIcACAADAVwiwAAAA8JWMKX0CSP2qD55hkVHZUvo00ozoYe1S+hQAAPA1KrAAAADwlRQLsFOmTLGvv/7aUrM333zTli1bFnw+fPhwW7VqVbzbJGSdpLhY+wUAAPCbFAuwX3zxhU2cONFSs5dfftn++OOP4PPnn38+LNDq9TVr1oRtE3Od5HKx9gsAAOA3KdYDe/3119vZs2fNTx599FGrWrVq8Pmzzz5rlSpVco+41rlYxwYAAEivLkqAnTNnjv3P//yP+z5v3rxWp04dq1evXtg6mTJlCguwqshmy5bNKlasaN99951lyZLF7rrrLvfatm3bbPr06Xbo0CFr2rSpXX755WH7WrFihc2ePdvtr1mzZue8/uKLL9pNN91k27dvt8WLF7tz6ty5szteqIULF7rzLlmypLVu3fqc9xUVFWUZMmRw3//nP/+xU6dOuSqyKqM5cuSwAQMGhK2TnOcXc78JfU96P3pf3nv6+OOPrXnz5la9evU4fnoAAADpsIVAwe748ePu8ddff1m7du3skUceibeFYNy4cS4AXnfddbZ69Wo7ceKEW651ypUr576uX7/e7rjjDhs1alRwu5EjR1qtWrVs0aJFtnTpUrv66qtt2LBhYcd65plnrEuXLvb444/b33//7V5v0KCBnT59OrjOq6++6sKxwug333xjV111lR08eDDO2/g6v0AgEHyv3vnGvNWfXOcXc78J2UYht0WLFrZ8+XLXc6z39NRTT4W1RQAAAPjNRanAqtIXWsF8+OGH3e3v/v37uzAalx07dtjatWutYMGCwee33367Pffcc8EArCqmF+RUfdSt9XfffdcFW1FY7tGjh914441Wvnz54L6rVKniQrLs3bvXihcvbjNnznSBWft5+umn7aOPPrLu3bsHg+c999wT57nqPQ0ePNgdq1OnTrGuk1znF5f4ttm6datrcVDFtVu3bm6d9957z/r27Rvn/hTCvSAuMQM8AABAmh7Epdvmo0ePdlXA8ePHu5aA8w1CatmyZTC8itoGFFgfeOCB/3/CkZFWs2ZN9/3cuXPd19tuuy34uqqSup2uW/ahtNyTL18+K126tG3YsCHY8qCWBoVKT69evdyxLkRynV9c4ttGx1bbQeh7UoiO2d4QaujQoZY7d+7gQ20HAAAA6SLAvvDCC1a/fn374YcfbP/+/e4We0REhKsSxqdAgQJhz1WBLVKkiAuXsfnnn3+sUKFCYaFMxylWrJh7LZR6VENlzJjR3f4XVSsLFy4cFlgV/hQKL0RynV9c4ttGfcN6TzqeJ3PmzC48x2XQoEF24MCB4GPz5s0JfKcAAAA+biE4c+aM69f8/PPPrWPHjsFlr7zySqL3pfCnEKvtY6scKgju2rXLVWlDw6fCm15LqKJFi9rOnTtdT6sX+E6ePGn79u2Ld7vQcBib5Dq/pFDwj/meFG7je08K7XoAAACkqwqsQpLCX/bs2YPLPvjgA7cssdq2besCmHpIPXq+cuVK932TJk1cOFSLgkeDlfbs2eNG2ifUNddc46rEkydPDi5TP6yCc3xy5cplhw8fjvP15Dq/pNCxjx075gakecaOHXve9wQAAJDuKrDqdb3lllvc4KuePXu62/OzZs0653Z3QiujGnjUp08f145QoUIFmzdvntu3BoVp0JJ6bNXbqT5W3UJX8NRI+9C5Wc9H+3nyySfd+WrfGsmvHtXznbOmxFLf6Lp16yxPnjxuFoWY+02O80sK9a9qhgINGAt9T/rF4kJ7ewEAANLcLAQffvihq2ZqIFejRo3stddec8tC5z+N+YcMunbtes4cpqLw1bhxY5s6daobIa/5VzWvrEehURVUjb5XdVZBN+acswqnoSP+5e677w7bj2Yh0Ll688BqWqoxY8ZYjRo14vxjAhqkpum9NHDKG70fc53kOr+Y+03INkOGDHGV2AULFrj3pN5kfVXYBgAA8KuIgFIV0iRVhlW19ihsqzquAWShsz3ERdNoudkIBkywyKhzf7lA0kQPa8elAwAgnuyhweRq1Ux1f0oWF9/333/vpvBSBVutHAqwqsImJLwCAACkVlRg0zj9BbAff/zRsmbN6lokvDl0k/O3IAAAgORABRaO/nysHgAAAGkFw9EBAADgKwRYAAAA+AoBFgAAAL5CgAUAAICvEGABAADgKwRYAAAA+AoBFgAAAL5CgAUAAICvEGABAADgKwRYAAAA+AoBFgAAAL5CgAUAAICvEGABAADgKwRYAAAA+ErGlD4BpH7VB8+wyKhsKX0aqUr0sHYpfQoAAKRbVGABAADgK+kiwP73v/+1zZs3p/RpAAAAIBmkiwDbv39/W758uaV377//vkVHR6f0aQAAAFyQdBFg8b8eeOAB++OPP7gcAADA19LVIK5ly5bZn3/+afnz57eWLVtahgwZgq+NHz/e9u3bZ5GRkVasWDFr0KCB5cuXL2z706dP2w8//GA7duywqlWrWp06dcJeP3DggHv96NGjVrNmTatRo8Y5rQzXXnutHTx40JYuXWp58+a1Vq1aWcaMGW3x4sXu/MqWLWtNmjQ559wTuu8jR47Y77//7vat96h9y9ixY935z5gxw7Zv327ZsmWz2267LVmuKwAAwKWUbgLs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O58zZ87Yxo0bg+9f+z948GCc5w4AAJDmAqyCV926da1GjRpWokQJa926dVh4Unjr0KGDFSlSxK6++morVKiQjRo1Kvj6m2++aYsWLbIpU6ZYp06d3OP777+3qlWr2rFjx9w6f/75p3v+4IMPBrcbMmSIDRgwwH3/zjvvBLetXLmylS9f3n788cd4j6FAePz4cevTp487pyZNmlju3LntkUcecSEvtE1C61xxxRXufT755JPB17799lsrVaqUW65tBw0aFHZtNm3aZM2bN7fSpUtbvXr13HE++eSTsHXuuecedz7t27e3woULW7NmzVy7g0fH1nUYOnSoW0/nE1sLgVoaHn/88XjP5+eff7YyZcrY5Zdf7n4evXv3tgYNGtg333yTyJ86AACAjwPsd999Z2+88YYLXapiLl++3N59993g6wqdqlrqdVVKR44c6W7n//777+51BbOmTZvabbfdFqyO3nDDDRYZGWkLFixw68ydO9fKli3rvnr0vbaTf//738FtVaXt16+f3XzzzcEAHNsxtD8FYFUgdd4Km6pifv311/af//wn7D0qqL7++uvuPXz88cfB5T/88IMtXLjQvT99/9JLL9mSJUvca6rmXnfdde72v0K8tv3iiy/s7rvvDq4j06ZNC1ZgVektUKCA3X///cHXFeazZcvmzknrxdd3G9/5qOLao0cP98uEzkf9wLo+8fUFnzhxwlVnQx8AAAC+D7BdunQJ3spWBbFVq1bBcKpb4p9++qmrlhYsWNAtu+mmm6xRo0ZhITemqKgoV62dM2dOMKwq1KltQIFTX1WV9QKsR8FMo/Pbtm3rwvKKFSviPIbC2Pvvv++qkNqftlPl+Prrr7cvv/wybF2FvpjHkoceesiKFSvmvm/cuLGrfnrvfdasWe52f69evVxA1v5V9axdu7YLyaHOnj3rbvsreOpY2jYp4jufmTNnumsybNgw98tBxowZ7ZVXXol3fwr+quR6j5IlSybpvAAAAFLVHzIoXrx42PMcOXIEb4Grj1XhTO0FoWrWrOkqtfFRYFSQU/+nqo7PPfecu2WuUKswrAFMuhUuGuDUv39/FwJ1mz5TpkzuuGoTUGCMjSqeqpI+/fTTliFDhrDXYga1cuXKJfi9e1Nb6f3p3FVNjim013bEiBHuvSlU5suXz1VKFfwVsBM7SCu+81Hw1+uh+yxatKjlzZs3zv2pBUGh2KNzIsQCAIA0/Ze4smbN6r56t/I9eq7b4ucLsC+88IK7Ja5wpx5PLVM1VgFWPatarn7VG2+80fV/qn9VYfTUqVPu2AqxcVHIlfHjx7vb/PGJGXATQvvPkiWLu+0fl8WLF9tjjz3m2gT0fkQBXX2z8Z17Uuh6qOc3ptiWhVbC9QAAAEg302ipzzRPnjzBVgBRMFMIrVWrVnCZgp5CZyi1ECg4KsRec801FhER4QKs9hXa/6qqq1oA1MrgBc158+aFDcSK7RiXXXaZq3hOmjTpnPOOeS5JoTYJVSx16z6u/a9cudK1XXjhVRRmY4rt+iSWqtXbt293rQye33777ZxfLgAAANJ1BVZ9ls8884w99dRT7ta15i59++23XeD0ZhCQKlWquJHwClS67a1b9l4frAZQaRupU6eOuyWu6azGjBnjlqnnU6P8dZyHH37YtS3oqwJvqNiOoR5QDfhStbRdu3Zumi0NqlJ1WP2fF0KtCxo01rNnT7cvBXb1wn744Yeu71a9rppJQH2pL7/8srVs2dIFbw0Wi8k7d83EoDBboUKFRJ+PZkFQZVeD23Q8tTGoPUChP+a1AgAASLMBVoOE1HMaSgOVQmkWgpw5c7rAqYCo/tf58+db/vz5w9ZRdVAj9DWX6fTp0131Vv2jqrC2aNHCraew1bVrV1u6dGmw/1VtBAqd6mW98847XV+nptVSoNVx4zuG1td70PpfffWVC8OazkpTV8X3Hr1QqSAcSqFYVV3PBx984KYM+/zzz+2tt96yihUruuMrLIum/NKAMYVWzeuqqrC2idmXqwCv96NZBDSYSj3BMf+QQULOZ8KECW4aMAVX9bJqQJcCtkIxAACAX0UEYpttH2mC2ipCg7FmaVBvsb6quns+aolwsxEMmGCRUfH3MCen6GH/G/gBAED6cvD/sseBAwfiHdyerC0ESF00L6xaM9RzqzYMVWNV3U5IeAUAAEitqMCmYeof1qA49dpqVgINjhs4cGCCWwgS+lsQAABAckho9iDA4oI/RAAAAJcyeyTrNFoAAADAxUaABQAAgK8QYAEAAOArBFgAAAD4CgEWAAAAvsI8sIiT9zcuNCIQAADgYvMyx/n+zhYBFnHas2eP+6o/QwsAAHAp57LXdFpxIcAiTvny5XNfN23aFO+HCOf+9qjQv3nzZubPTQSuW9Jw3bhulxKfN67bxabKq8JrsWLF4l2PAIs4RUb+b4u0wit/yCDxdM24bly3S4XPG9ftUuLzxnW7mBJSNGMQFwAAAHyFAAsAAABfIcAiTlFRUTZ48GD3FQnHdUsarhvX7VLi88Z14/PmbxGB881TAAAAAKQiVGABAADgKwRYAAAA+AoBFgAAAL7CPLDpiNqdFy9e7CbYr1KlilWtWjVZtknKfv3k7Nmz9ssvv9iOHTusevXqVqFChQve5rfffrN169aFLcuTJ4+1bdvW0orTp0/bggULbO/evVarVi0rVapUgrbTdduwYYNde+21sc4FmNT9+sWJEyfsf/7nf+zw4cNWt25dK1KkyHm30X+DP/30k23dutU6d+5smTNnDnv9+++/t127doUtK126tNWvX9/SiqNHj7rrpuun95U/f/7zbrNx40b766+/rECBAnbllVeec92Sul8/0YTxP//8s/sMNWzYMEHzb+rfrlWrVlmhQoWsdu3aliFDhrDXJ0+e7K5XKP07qEdasW/fPps/f75lzJjRGjVqZNmzZz/vNvr/yKVLl7prrOuWLVu2ZNlvuqVBXEj7jh49GmjVqlWgUKFCgdatWwdy5swZ6N27d+Ds2bMXtE1S9usn+/fvD1x99dWBYsWKBVq2bBnIli1bYODAgRe8zd133x0oUaJEoHv37sHHI488Ekgrtm3bFqhevXqgTJkygebNmweyZs0aeOmll+LdZvLkyYHLL788UKFCBQ0sDfz111/Jsl8/Wbt2rXtvlStXDjRp0sR9dt5///14t/nwww/d+t5127Vr1znrNGzYMFCtWrWwz9sbb7wRSCt+//33QNGiRQM1atRw7zVHjhyBL774Is71t2zZErj22mvdtW7Xrl2gSpUqgdKlSwd+/fXXC9qv38ybNy+QL1++QO3atQN169YN5MmTJzB79uw411+zZk3gmmuucZ+19u3bB8qVK+c+eytWrAhbL3/+/IH69euHfd4mTpwYSCumTJni/r9O71H/Zun//2J+dkIdPHgw0LVrV3e9OnToEKhZs6a7Rt9+++0F7Te9I8CmE4MHD3aBavv27e750qVLA5kzZw58/vnnF7RNUvbrJ/fcc0+gUqVKLpTKTz/95EJCfP/IJ2QbBdguXboE0ir9H5b+T/HYsWPBcBoRERFYsmRJnNvoM6PAoEdcATYp+/UThQP9Inj69Gn3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",
      "text/plain": [
       "<Figure size 700x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "m = rf().fit(tr[BASE], y)\n",
    "pd.Series(m.feature_importances_, index=BASE).sort_values().plot.barh(figsize=(7, 5), title=\"Feature importance\");"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c64f122",
   "metadata": {},
   "source": [
    "`area` dominates (about a third of all importance), then furnishing, stories, bathrooms and bedrooms. That matches the EDA hypotheses from 01.\n",
    "Note that importance shows what the model *uses*, not cause and effect.\n",
    "\n",
    "## Decision\n",
    "No new feature beat the noise, so we keep the **12 raw columns**. Simpler is better when the evidence is unclear.\n",
    "(On a big dataset the same ideas can matter a lot. See `extra_california/04_feature_engineering.ipynb`, where distance-to-city features added +3%.)\n",
    "\n",
    "Next: **05_models_and_tuning**. If features aren't the lever here, maybe the model is."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
