{
 "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",
    "\n",
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\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": [
    "\n",
    "def standard_units(any_numbers):\n",
    "    \"Convert any array of numbers to standard units.\"\n",
    "    return (any_numbers - np.mean(any_numbers))/np.std(any_numbers)  \n",
    "\n",
    "def correlation(t, x, y):\n",
    "    return np.mean(standard_units(t[x])*standard_units(t[y]))\n",
    "\n",
    "def slope(table, x, y):\n",
    "    r = correlation(table, x, y)\n",
    "    return r * np.std(table[y])/np.std(table[x])\n",
    "\n",
    "def intercept(table, x, y):\n",
    "    a = slope(table, x, y)\n",
    "    return np.mean(table[y]) - a * np.mean(table[x])\n",
    "\n",
    "def fit(table, x, y):\n",
    "    a = slope(table, x, y)\n",
    "    b = intercept(table, x, y)\n",
    "    return a * table[x] + b\n",
    "\n",
    "def scatter_fit(table, x, y):\n",
    "    #fig, ax = plt.subplots(figsize=(7,6))\n",
    "    plt.scatter(table[x], \n",
    "               table[y],  \n",
    "               color='darkblue',\n",
    "               s=20)\n",
    "    \n",
    "    plt.plot(table[x], fit(table, x, y), lw=2, color='gold')\n",
    "    plt.xlabel(x)\n",
    "    plt.ylabel(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A Regression Model\n",
    "\n",
    "In brief, such models say that the underlying relation between the two variables is perfectly linear; this straight line is the *signal* that we would like to identify. However, we are not able to see the line clearly. What we see are points that are scattered around the line. In each of the points, the signal has been contaminated by *random noise*. Our inferential goal, therefore, is to separate the signal from the noise.\n",
    "\n",
    "In greater detail, the regression model specifies that the points in the scatter plot are generated at random as follows.\n",
    "\n",
    "- The relation between $x$ and $y$ is perfectly linear. We cannot see this \"true line\" but it exists.\n",
    "- The scatter plot is created by taking points on the line and pushing them off the line vertically, either above or below, as follows:\n",
    "    - For each $x$, find the corresponding point on the true line (that's the signal), and then generate the noise or error.\n",
    "    - The errors are drawn at random with replacement from a population of errors that has a normal distribution with mean 0.\n",
    "    - Create a point whose horizontal coordinate is $x$ and whose vertical coordinate is \"the height of the true line at $x$, plus the error\".\n",
    "- Finally, erase the true line from the scatter, and display just the points created."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Based on this scatter plot, how should we estimate the true line? The best line that we can put through a scatter plot is the regression line. So the regression line is a natural estimate of the true line. \n",
    "\n",
    "The simulation below shows how close the regression line is to the true line. The first panel shows how the scatter plot is generated from the true line. The second shows the scatter plot that we see. The third shows the regression line through the plot. The fourth shows both the regression line and the true line.\n",
    "\n",
    "To run the simulation, call the function `draw_and_compare` with three arguments: the slope of the true line, the intercept of the true line, and the sample size.\n",
    "\n",
    "Run the simulation a few times, with different values for the slope and intercept of the true line, and varying sample sizes. Because all the points are generated according to the model, you will see that the regression line is a good estimate of the true line if the sample size is moderately large."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [],
   "source": [
    "def draw_and_compare(true_slope, true_int, sample_size):\n",
    "    x = np.random.normal(50, 5, sample_size)\n",
    "    xlims = np.array([np.min(x), np.max(x)])\n",
    "    eps = np.random.normal(0, 6, sample_size)\n",
    "    y = (true_slope*x + true_int) + eps\n",
    "    tyche = pd.DataFrame({'x':x,'y':y})\n",
    "\n",
    "    plt.figure(figsize=(6, 16))\n",
    "    \n",
    "    plt.subplot(4, 1, 1)\n",
    "    plt.scatter(tyche['x'], tyche['y'], s=20)\n",
    "    plt.plot(xlims, true_slope*xlims + true_int, lw=2, color='green')\n",
    "    plt.title('True Line, and Points Created')\n",
    "\n",
    "#---\n",
    "    plt.subplot(4, 1, 2)\n",
    "    plt.scatter(tyche['x'], tyche['y'], s=20)\n",
    "    plt.title('What We Get to See')\n",
    "    \n",
    "#---\n",
    "    plt.subplot(4, 1, 3)\n",
    "    scatter_fit(tyche, 'x', 'y')\n",
    "    plt.xlabel(\"\")\n",
    "    plt.ylabel(\"\")\n",
    "    plt.title('Regression Line: Estimate of True Line')\n",
    "#---\n",
    "    plt.subplot(4, 1, 4)\n",
    "    scatter_fit(tyche, 'x', 'y')\n",
    "    \n",
    "    xlims = np.array([np.min(tyche['x']), np.max(tyche['x'])])\n",
    "    plt.plot(xlims, true_slope*xlims + true_int, lw=2, color='green')\n",
    "    plt.ylabel(\"\")\n",
    "    plt.title(\"Regression Line and True Line\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 78512 characters]\n",
      "text/plain": [
       "<Figure size 432x1152 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# The true line,\n",
    "# the points created,\n",
    "# and our estimate of the true line.\n",
    "# Arguments: true slope, true intercept, number of points\n",
    "\n",
    "draw_and_compare(4, -5, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In reality, of course, we will never see the true line. What the simulation shows that if the regression model looks plausible, and if we have a large sample, then the regression line is a good approximation to the true line."
   ]
  }
 ],
 "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
}
