{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "path_data = '../data/'\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "plt.style.use('fivethirtyeight')\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 15. Prediction\n",
    "\n",
    "An important aspect of data science is to find out what data can tell us about the future. What do data about climate and pollution say about temperatures a few decades from now? Based on a person's internet profile, which websites are likely to interest them? How can a patient's medical history be used to judge how well he or she will respond to a treatment?\n",
    "\n",
    "To answer such questions, data scientists have developed methods for making *predictions*. In this chapter we will study one of the most commonly used ways of predicting the value of one variable based on the value of another."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The foundations of the method were laid by [Sir Francis Galton](https://en.wikipedia.org/wiki/Francis_Galton). As we saw in Section 7.1, Galton studied how physical characteristics are passed down from one generation to the next. Among his best known work is the prediction of the heights of adults based on the heights of their parents. We have studied the dataset that Galton collected for this. The table `heights` contains his data on the midparent height and child's height (all in inches) for a population of 934 adult \"children\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Galton's data on heights of parents and their adult children\n",
    "galton = pd.read_csv(path_data + 'galton.csv')\n",
    "heights = pd.DataFrame(\n",
    "    {'MidParent':galton['midparentHeight'],\n",
    "    'Child':galton['childHeight']}\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "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>MidParent</th>\n",
       "      <th>Child</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>75.43</td>\n",
       "      <td>73.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>75.43</td>\n",
       "      <td>69.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>75.43</td>\n",
       "      <td>69.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>75.43</td>\n",
       "      <td>69.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>73.66</td>\n",
       "      <td>73.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>929</th>\n",
       "      <td>66.64</td>\n",
       "      <td>64.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>930</th>\n",
       "      <td>66.64</td>\n",
       "      <td>62.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>931</th>\n",
       "      <td>66.64</td>\n",
       "      <td>61.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>932</th>\n",
       "      <td>65.27</td>\n",
       "      <td>66.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>933</th>\n",
       "      <td>65.27</td>\n",
       "      <td>57.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>934 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     MidParent  Child\n",
       "0        75.43   73.2\n",
       "1        75.43   69.2\n",
       "2        75.43   69.0\n",
       "3        75.43   69.0\n",
       "4        73.66   73.5\n",
       "..         ...    ...\n",
       "929      66.64   64.0\n",
       "930      66.64   62.0\n",
       "931      66.64   61.0\n",
       "932      65.27   66.5\n",
       "933      65.27   57.0\n",
       "\n",
       "[934 rows x 2 columns]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "heights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 29352 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "heights.plot.scatter('MidParent', 'Child')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The primary reason for collecting the data was to be able to predict the adult height of a child born to parents similar to those in the dataset. We made these predictions in Section 7.1, after noticing the positive association between the two variables. \n",
    "\n",
    "Our approach was to base the prediction on all the points that correspond to a midparent height of around the midparent height of the new person. To do this, we wrote a function called `predict_child` which takes a midparent height as its argument and returns the average height of all the children who had midparent heights within half an inch of the argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def predict_child(mpht):\n",
    "    \"\"\"Return a prediction of the height of a child \n",
    "    whose parents have a midparent height of mpht.\n",
    "    \n",
    "    The prediction is the average height of the children \n",
    "    whose midparent height is in the range mpht plus or minus 0.5 inches.\n",
    "    \"\"\"\n",
    "    \n",
    "    close_points = heights[(heights['MidParent'] > mpht-0.5) & (heights['MidParent'] < mpht + 0.5)]\n",
    "                            \n",
    "    return close_points['Child'].mean()                       "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We applied the function to the column of `Midparent` heights, visualized our results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "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>MidParent</th>\n",
       "      <th>Child</th>\n",
       "      <th>Prediction</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>75.43</td>\n",
       "      <td>73.2</td>\n",
       "      <td>70.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>75.43</td>\n",
       "      <td>69.2</td>\n",
       "      <td>70.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>75.43</td>\n",
       "      <td>69.0</td>\n",
       "      <td>70.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>75.43</td>\n",
       "      <td>69.0</td>\n",
       "      <td>70.100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>73.66</td>\n",
       "      <td>73.5</td>\n",
       "      <td>70.415789</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>929</th>\n",
       "      <td>66.64</td>\n",
       "      <td>64.0</td>\n",
       "      <td>65.156579</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>930</th>\n",
       "      <td>66.64</td>\n",
       "      <td>62.0</td>\n",
       "      <td>65.156579</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>931</th>\n",
       "      <td>66.64</td>\n",
       "      <td>61.0</td>\n",
       "      <td>65.156579</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>932</th>\n",
       "      <td>65.27</td>\n",
       "      <td>66.5</td>\n",
       "      <td>64.229630</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>933</th>\n",
       "      <td>65.27</td>\n",
       "      <td>57.0</td>\n",
       "      <td>64.229630</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>934 rows × 3 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     MidParent  Child  Prediction\n",
       "0        75.43   73.2   70.100000\n",
       "1        75.43   69.2   70.100000\n",
       "2        75.43   69.0   70.100000\n",
       "3        75.43   69.0   70.100000\n",
       "4        73.66   73.5   70.415789\n",
       "..         ...    ...         ...\n",
       "929      66.64   64.0   65.156579\n",
       "930      66.64   62.0   65.156579\n",
       "931      66.64   61.0   65.156579\n",
       "932      65.27   66.5   64.229630\n",
       "933      65.27   57.0   64.229630\n",
       "\n",
       "[934 rows x 3 columns]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Apply predict_child to all the midparent heights\n",
    "\n",
    "heights_with_predictions = heights.copy()\n",
    "\n",
    "heights_with_predictions['Prediction'] = heights['MidParent'].map(predict_child)\n",
    "\n",
    "heights_with_predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 47048 characters]\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Draw the original scatter plot along with the predicted values\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(8,5))\n",
    "\n",
    "ax.scatter(heights_with_predictions['MidParent'], \n",
    "           heights_with_predictions['Child'], \n",
    "           label='Child', \n",
    "           color='darkblue')\n",
    "\n",
    "ax.scatter(heights_with_predictions['MidParent'], \n",
    "           heights_with_predictions['Prediction'], \n",
    "           label='Prediction', \n",
    "           color='gold')\n",
    "\n",
    "x_label = 'MidParent'\n",
    "\n",
    "y_label = ''\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "plt.ylabel(y_label)\n",
    "\n",
    "plt.xlabel(x_label)\n",
    "\n",
    "ax.legend(bbox_to_anchor=(1.04,1), loc=\"upper left\", frameon=False)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The prediction at a given midparent height lies roughly at the center of the vertical strip of points at the given height. This method of prediction is called *regression.* Later in this chapter we will see where this term came from. We will also see whether we can avoid our arbitrary definitions of \"closeness\" being \"within 0.5 inches\". But first we will develop a measure that can be used in many settings to decide how good one variable will be as a predictor of another."
   ]
  }
 ],
 "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
}
