{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [],
   "source": [
    "path_data = '../../data/'\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import math\n",
    "import scipy.stats as stats\n",
    "\n",
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "plt.style.use('fivethirtyeight')\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [],
   "source": [
    "def standard_units(x):\n",
    "    return (x - np.mean(x))/np.std(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def distance(point1, point2):\n",
    "    \"\"\"The distance between two arrays of numbers.\"\"\"\n",
    "    return np.sqrt(np.sum((point1 - point2)**2))\n",
    "\n",
    "def all_distances(training, point):\n",
    "    \"\"\"The distance between p (an array of numbers) and the numbers in row i of attribute_table.\"\"\"\n",
    "    attributes = training.drop(columns=['Class'])\n",
    "    def distance_from_point(row):\n",
    "        return distance(point, np.array(row))\n",
    "    return attributes.apply(distance_from_point, axis=1)\n",
    "\n",
    "def table_with_distances(training, point):\n",
    "    \"\"\"A copy of the training table with the distance from each row to array p.\"\"\"\n",
    "    training1 = training.copy()\n",
    "    training1['Distance'] = all_distances(training1, point)\n",
    "    return training1\n",
    "\n",
    "\n",
    "def closest(training, point, k):\n",
    "    \"\"\"A table containing the k closest rows in the training table to array p.\"\"\"\n",
    "    with_dists = table_with_distances(training, point)\n",
    "    sorted_by_distance = with_dists.sort_values(by=['Distance'])\n",
    "    topk = sorted_by_distance.take(np.arange(k))\n",
    "    return topk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def classify_grid(training, test, k):\n",
    "    ckd_new1 = pd.DataFrame(columns=['Hemoglobin', 'Glucose', 'Class', 'Distance'])\n",
    "    empty = np.array([])\n",
    "    for i in range(len(test)):\n",
    "        ckd_new2 = closest(training, np.array([test.iloc[i]]), k)\n",
    "        ones = len(ckd_new2[ckd_new2['Class'] == '1'])\n",
    "        zeros = len(ckd_new2[ckd_new2['Class'] == '0'])\n",
    "        if ones > zeros:\n",
    "            empty = np.append(empty, 1)\n",
    "        else:\n",
    "            empty = np.append(empty, 0)\n",
    "    return empty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "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>Hemoglobin</th>\n",
       "      <th>Glucose</th>\n",
       "      <th>White Blood Cell Count</th>\n",
       "      <th>Class</th>\n",
       "      <th>Color</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-0.865744</td>\n",
       "      <td>-0.221549</td>\n",
       "      <td>-0.569768</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-1.457446</td>\n",
       "      <td>-0.947597</td>\n",
       "      <td>1.162684</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-1.004968</td>\n",
       "      <td>3.841231</td>\n",
       "      <td>-1.275582</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-2.814879</td>\n",
       "      <td>0.396364</td>\n",
       "      <td>0.809777</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-2.083954</td>\n",
       "      <td>0.643529</td>\n",
       "      <td>0.232293</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>153</th>\n",
       "      <td>0.700526</td>\n",
       "      <td>0.133751</td>\n",
       "      <td>-0.569768</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>154</th>\n",
       "      <td>0.978974</td>\n",
       "      <td>-0.870358</td>\n",
       "      <td>-0.216861</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>155</th>\n",
       "      <td>0.735332</td>\n",
       "      <td>-0.484162</td>\n",
       "      <td>-0.601850</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>156</th>\n",
       "      <td>0.178436</td>\n",
       "      <td>-0.267893</td>\n",
       "      <td>-0.409356</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>157</th>\n",
       "      <td>0.735332</td>\n",
       "      <td>-0.005280</td>\n",
       "      <td>-0.537686</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>158 rows × 5 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     Hemoglobin   Glucose  White Blood Cell Count Class     Color\n",
       "0     -0.865744 -0.221549               -0.569768     1  darkblue\n",
       "1     -1.457446 -0.947597                1.162684     1  darkblue\n",
       "2     -1.004968  3.841231               -1.275582     1  darkblue\n",
       "3     -2.814879  0.396364                0.809777     1  darkblue\n",
       "4     -2.083954  0.643529                0.232293     1  darkblue\n",
       "..          ...       ...                     ...   ...       ...\n",
       "153    0.700526  0.133751               -0.569768     0      gold\n",
       "154    0.978974 -0.870358               -0.216861     0      gold\n",
       "155    0.735332 -0.484162               -0.601850     0      gold\n",
       "156    0.178436 -0.267893               -0.409356     0      gold\n",
       "157    0.735332 -0.005280               -0.537686     0      gold\n",
       "\n",
       "[158 rows x 5 columns]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ckd = pd.read_csv(path_data + 'ckd.csv')\n",
    "ckd.rename(columns={'Blood Glucose Random':'Glucose'}, inplace=True)\n",
    "\n",
    "\n",
    "ckd_Standard_Unit = pd.DataFrame({'Hemoglobin':standard_units(ckd['Hemoglobin']), \n",
    "                       'Glucose':standard_units(ckd['Glucose']), \n",
    "                       'White Blood Cell Count':standard_units(ckd['White Blood Cell Count']), \n",
    "                       'Class':ckd['Class'].astype(str)})\n",
    "\n",
    "color_table = pd.DataFrame(\n",
    "    {'Class':np.array([1, 0]),\n",
    "    'Color':np.array(['darkblue', 'gold'])}, index=np.array([1,0]))\n",
    "     \n",
    "color_table['Class'] = color_table['Class'].astype(str)\n",
    "\n",
    "ckd_combined = pd.merge(ckd_Standard_Unit, color_table, on='Class')\n",
    "\n",
    "ckd_combined"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Training and Testing\n",
    "How good is our nearest neighbor classifier? To answer this we'll need to find out how frequently our classifications are correct. If a patient has chronic kidney disease, how likely is our classifier to pick that up?\n",
    "\n",
    "If the patient is in our training set, we can find out immediately. We already know what class the patient is in. So we can just compare our prediction and the patient's true class.\n",
    "\n",
    "But the point of the classifier is to make predictions for *new* patients not in our training set. We don't know what class these patients are in but we can make a prediction based on our classifier. How to find out whether the prediction is correct?\n",
    "\n",
    "One way is to wait for further medical tests on the patient and then check whether or not our prediction agrees with the test results. With that approach, by the time we can say how likely our prediction is to be accurate, it is no longer useful for helping the patient.\n",
    "\n",
    "Instead, we will try our classifier on some patients whose true classes are known.  Then, we will compute the proportion of the time our classifier was correct.  This proportion will serve as an estimate of the proportion of all new patients whose class our classifier will accurately predict.  This is called *testing*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Overly Optimistic \"Testing\"\n",
    "The training set offers a very tempting set of patients on whom to test out our classifier, because we know the class of each patient in the training set.\n",
    "\n",
    "But let's be careful ... there will be pitfalls ahead if we take this path. An example will show us why.\n",
    "\n",
    "Suppose we use a 1-nearest neighbor classifier to predict whether a patient has chronic kidney disease, based on glucose and white blood cell count."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 28776 characters]\n",
      "text/plain": [
       "<Figure size 504x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "glucose_color_darkblue = ckd_combined[ckd_combined['Color'] == 'darkblue']\n",
    "glucose_color_gold = ckd_combined[ckd_combined['Color'] == 'gold']\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7,6))\n",
    "\n",
    "ax.scatter(glucose_color_darkblue['White Blood Cell Count'], \n",
    "           glucose_color_darkblue['Glucose'],  \n",
    "           label='Color=darkblue', \n",
    "           color='darkblue')\n",
    "\n",
    "ax.scatter(glucose_color_gold['White Blood Cell Count'], \n",
    "           glucose_color_gold['Glucose'],  \n",
    "           label='Color=gold', \n",
    "           color='gold')\n",
    "\n",
    "x_label = 'White Blood Cell Count'\n",
    "\n",
    "y_label = 'Glucose'\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "plt.ylabel(y_label)\n",
    "\n",
    "ax.legend(bbox_to_anchor=(1.04,1), loc=\"upper left\")\n",
    "\n",
    "plt.xlabel(x_label)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Earlier, we said that we expect to get some classifications wrong, because there's some intermingling of blue and gold points in the lower-left.\n",
    "\n",
    "But what about the points in the training set, that is, the points already on the scatter? Will we ever mis-classify them?\n",
    "\n",
    "The answer is no. Remember that 1-nearest neighbor classification looks for the point *in the training set* that is nearest to the point being classified. Well, if the point being classified is already in the training set, then its nearest neighbor in the training set is itself! And therefore it will be classified as its own color, which will be correct because each point in the training set is already correctly colored.\n",
    "\n",
    "In other words, **if we use our training set to \"test\" our 1-nearest neighbor classifier, the classifier will pass the test 100% of the time.**\n",
    "\n",
    "Mission accomplished. What a great classifier! \n",
    "\n",
    "No, not so much. A new point in the lower-left might easily be mis-classified, as we noted earlier. \"100% accuracy\" was a nice dream while it lasted.\n",
    "\n",
    "The lesson of this example is *not* to use the training set to test a classifier that is based on it."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generating a Test Set\n",
    "In earlier chapters, we saw that random sampling could be used to estimate the proportion of individuals in a population that met some criterion.  Unfortunately, we have just seen that the training set is not like a random sample from the population of all patients, in one important respect: Our classifier guesses correctly for a higher proportion of individuals in the training set than it does for individuals in the population.\n",
    "\n",
    "When we computed confidence intervals for numerical parameters, we wanted to have many new random samples from a population, but we only had access to a single sample.  We solved that problem by taking bootstrap resamples from our sample.\n",
    "\n",
    "We will use an analogous idea to test our classifier. We will *create two samples out of the original training set*, use one of the samples as our training set, and *the other one for testing*. \n",
    "\n",
    "So we will have three groups of individuals:\n",
    "- a training set on which we can do any amount of exploration to build our classifier;\n",
    "- a separate testing set on which to try out our classifier and see what fraction of times it classifies correctly;\n",
    "- the underlying population of individuals for whom we don't know the true classes; the hope is that our classifier will succeed about as well for these individuals as it did for our testing set."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "How to generate the training and testing sets? You've guessed it – we'll select at random.\n",
    "\n",
    "There are 158 individuals in `ckd`. Let's use a random half of them for training and the other half for testing. To do this, we'll shuffle all the rows, take the first 79 as the training set, and the remaining 79 for testing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "shuffled_ckd = ckd_combined.sample(len(ckd_combined), replace=False)\n",
    "\n",
    "shuffled_ckd\n",
    "\n",
    "training = shuffled_ckd.take(np.arange(79))\n",
    "\n",
    "testing = shuffled_ckd.take(np.arange(79, 158))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's construct our classifier based on the points in the training sample:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 25572 characters]\n",
      "text/plain": [
       "<Figure size 504x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "training_darkblue = training[training['Color'] == 'darkblue']\n",
    "training_gold = training[training['Color'] == 'gold']\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7,6))\n",
    "\n",
    "ax.scatter(training_darkblue['White Blood Cell Count'], \n",
    "           training_darkblue['Glucose'],  \n",
    "           label='Color=darkblue', \n",
    "           color='darkblue')\n",
    "\n",
    "ax.scatter(training_gold['White Blood Cell Count'], \n",
    "           training_gold['Glucose'],  \n",
    "           label='Color=gold', \n",
    "           color='gold')\n",
    "\n",
    "x_label = 'White Blood Cell Count'\n",
    "\n",
    "y_label = 'Glucose'\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "plt.ylabel(y_label)\n",
    "\n",
    "ax.legend(bbox_to_anchor=(1.04,1), loc=\"upper left\")\n",
    "\n",
    "plt.xlabel(x_label)\n",
    "\n",
    "plt.xlim(-2, 6)\n",
    "plt.ylim(-2, 6);\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We get the following classification regions and decision boundary:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [],
   "source": [
    "x_array = np.array([])\n",
    "y_array = np.array([])\n",
    "for x in np.arange(-2, 6.1, 0.25):\n",
    "    for y in np.arange(-2, 6.1, 0.25):\n",
    "        x_array = np.append(x_array, x)\n",
    "        y_array = np.append(y_array, y)\n",
    "        \n",
    "test_grid = pd.DataFrame(\n",
    "    {'Glucose':x_array,\n",
    "    'White Blood Cell Count':y_array}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1089"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(test_grid)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c_training = classify_grid(training.drop(columns=['Hemoglobin', 'Color']), test_grid, 1)\n",
    "c_training[0:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1089"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(c_training)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "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>Glucose</th>\n",
       "      <th>White Blood Cell Count</th>\n",
       "      <th>Class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-2.0</td>\n",
       "      <td>-2.00</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-2.0</td>\n",
       "      <td>-1.75</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-2.0</td>\n",
       "      <td>-1.50</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-2.0</td>\n",
       "      <td>-1.25</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-2.0</td>\n",
       "      <td>-1.00</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Glucose  White Blood Cell Count Class\n",
       "0     -2.0                   -2.00     1\n",
       "1     -2.0                   -1.75     1\n",
       "2     -2.0                   -1.50     1\n",
       "3     -2.0                   -1.25     1\n",
       "4     -2.0                   -1.00     1"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_grid['Class'] = c_training.astype(int)\n",
    "test_grid['Class'] = test_grid['Class'].astype(str)\n",
    "test_grid.head(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Join df's"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "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>Glucose</th>\n",
       "      <th>White Blood Cell Count</th>\n",
       "      <th>Class</th>\n",
       "      <th>Color</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-2.00</td>\n",
       "      <td>-2.00</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-2.00</td>\n",
       "      <td>-1.75</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-2.00</td>\n",
       "      <td>-1.50</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-2.00</td>\n",
       "      <td>-1.25</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-2.00</td>\n",
       "      <td>-1.00</td>\n",
       "      <td>1</td>\n",
       "      <td>darkblue</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1084</th>\n",
       "      <td>0.75</td>\n",
       "      <td>-0.50</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1085</th>\n",
       "      <td>0.75</td>\n",
       "      <td>1.00</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1086</th>\n",
       "      <td>0.75</td>\n",
       "      <td>1.25</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1087</th>\n",
       "      <td>0.75</td>\n",
       "      <td>1.50</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1088</th>\n",
       "      <td>1.00</td>\n",
       "      <td>1.25</td>\n",
       "      <td>0</td>\n",
       "      <td>gold</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1089 rows × 4 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      Glucose  White Blood Cell Count Class     Color\n",
       "0       -2.00                   -2.00     1  darkblue\n",
       "1       -2.00                   -1.75     1  darkblue\n",
       "2       -2.00                   -1.50     1  darkblue\n",
       "3       -2.00                   -1.25     1  darkblue\n",
       "4       -2.00                   -1.00     1  darkblue\n",
       "...       ...                     ...   ...       ...\n",
       "1084     0.75                   -0.50     0      gold\n",
       "1085     0.75                    1.00     0      gold\n",
       "1086     0.75                    1.25     0      gold\n",
       "1087     0.75                    1.50     0      gold\n",
       "1088     1.00                    1.25     0      gold\n",
       "\n",
       "[1089 rows x 4 columns]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "color_table = pd.DataFrame(\n",
    "    {'Class':np.array([1, 0]),\n",
    "    'Color':np.array(['darkblue', 'gold'])}, index=np.array([1,0]))\n",
    "     \n",
    "color_table['Class'] = color_table['Class'].astype(str)\n",
    "\n",
    "test_grid_combined = pd.merge(test_grid, color_table, on='Class')\n",
    "\n",
    "test_grid_combined"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 29900 characters]\n",
      "text/plain": [
       "<Figure size 504x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "training_darkblue = test_grid_combined[test_grid_combined['Color'] == 'darkblue']\n",
    "training_gold = test_grid_combined[test_grid_combined['Color'] == 'gold']\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7,6))\n",
    "\n",
    "ax.scatter(training_darkblue['White Blood Cell Count'], \n",
    "           training_darkblue['Glucose'],  \n",
    "           label='Color=darkblue', \n",
    "           alpha=0.4, \n",
    "           color='darkblue', \n",
    "           s=30)\n",
    "\n",
    "ax.scatter(training_gold['White Blood Cell Count'], \n",
    "           training_gold['Glucose'],  \n",
    "           label='Color=gold', \n",
    "           alpha=0.4, \n",
    "           s=30, \n",
    "           color='gold')\n",
    "\n",
    "x_label = 'White Blood Cell Count'\n",
    "\n",
    "y_label = 'Glucose'\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "plt.ylabel(y_label)\n",
    "\n",
    "ax.legend(bbox_to_anchor=(1.04,1), loc=\"upper left\")\n",
    "\n",
    "plt.xlabel(x_label)\n",
    "\n",
    "plt.xlim(-2, 6)\n",
    "plt.ylim(-2, 6);\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Place the *test* data on this graph and you can see at once that while the classifier got almost all the points right, there are some mistakes.  For example, some blue points of the test set fall in the gold region of the classifier."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 40576 characters]\n",
      "text/plain": [
       "<Figure size 504x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "training_darkblue = test_grid_combined[test_grid_combined['Color'] == 'darkblue']\n",
    "training_gold = test_grid_combined[test_grid_combined['Color'] == 'gold']\n",
    "\n",
    "testing_darkblue = testing[testing['Color'] == 'darkblue']\n",
    "testing_gold = testing[testing['Color'] == 'gold']\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7,6))\n",
    "\n",
    "ax.scatter(training_darkblue['White Blood Cell Count'], \n",
    "           training_darkblue['Glucose'],   \n",
    "           alpha=0.4, \n",
    "           color='darkblue', \n",
    "           s=30)\n",
    "\n",
    "ax.scatter(training_gold['White Blood Cell Count'], \n",
    "           training_gold['Glucose'],   \n",
    "           alpha=0.4, \n",
    "           s=30, \n",
    "           color='gold')\n",
    "\n",
    "ax.scatter(testing_darkblue['White Blood Cell Count'], \n",
    "           testing_darkblue['Glucose'],   \n",
    "           color='darkblue', label='Color=darkblue', ec='darkblue',  s=30)\n",
    "\n",
    "ax.scatter(testing_gold['White Blood Cell Count'], \n",
    "           testing_gold['Glucose'],   \n",
    "           color='gold', label='Color=gold', ec='darkblue', s=30)\n",
    "\n",
    "x_label = 'White Blood Cell Count'\n",
    "\n",
    "y_label = 'Glucose'\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "plt.ylabel(y_label)\n",
    "\n",
    "ax.legend(bbox_to_anchor=(1.04,1), loc=\"upper left\")\n",
    "\n",
    "plt.xlabel(x_label)\n",
    "\n",
    "plt.xlim(-2, 6)\n",
    "plt.ylim(-2, 6);\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some errors notwithstanding, it looks like the classifier does fairly well on the test set. Assuming that the original sample was drawn randomly from the underlying population, the hope is that the classifier will perform with similar accuracy on the overall population, since the test set was chosen randomly from the original sample."
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "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.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
