{
 "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",
    "from scipy import stats\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": [
    "# The Variability of the Sample Mean\n",
    "By the Central Limit Theorem, the probability distribution of the mean of a large random sample is roughly normal. The bell curve is centered at the population mean. Some of the sample means are higher, and some lower, but the deviations from the population mean are roughly symmetric on either side, as we have seen repeatedly. Formally, probability theory shows that the sample mean is an *unbiased* estimate of the population mean.\n",
    "\n",
    "In our simulations, we also noticed that the means of larger samples tend to be more tightly clustered around the population mean than means of smaller samples. In this section, we will quantify the variability of the sample mean and develop a relation between the variability and the sample size."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start with our table of flight delays. The mean delay is about 16.7 minutes, and the distribution of delays is skewed to the right."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "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>Delay</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>257</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>28</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13820</th>\n",
       "      <td>-4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13821</th>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13822</th>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13823</th>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13824</th>\n",
       "      <td>-2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>13825 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "       Delay\n",
       "0        257\n",
       "1         28\n",
       "2         -3\n",
       "3          0\n",
       "4         64\n",
       "...      ...\n",
       "13820     -4\n",
       "13821      8\n",
       "13822      3\n",
       "13823     -1\n",
       "13824     -2\n",
       "\n",
       "[13825 rows x 1 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "united = pd.read_csv(path_data + 'united_summer2015.csv')\n",
    "delay = united[['Delay']]\n",
    "delay"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Delay    16.658156\n",
       "dtype: float64"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pop_mean = np.mean(delay)\n",
    "pop_mean"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "tags": [
     "remove_input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 15884 characters]\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "source = delay\n",
    "\n",
    "source_col = ''\n",
    "\n",
    "bins = np.arange(-20, 300, 10)\n",
    "\n",
    "if source_col =='':\n",
    "    source = source\n",
    "else:\n",
    "    source = source[source_col]\n",
    "\n",
    "unit = ''\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(7,5))\n",
    "\n",
    "ax.hist(source, bins=bins, density=True, color=('darkblue'), alpha=0.8, ec='white', zorder=5)\n",
    "\n",
    "ax.scatter(pop_mean, -0.0008, marker='^', color='darkblue', s=60, \n",
    "           zorder=15).set_clip_on(False)\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "y_label = 'Percent per ' + (unit if unit else 'unit')\n",
    "\n",
    "x_label = 'Delay'\n",
    "\n",
    "ax.set_yticklabels(['{:g}'.format(x * 100) for x in y_vals])\n",
    "\n",
    "plt.ylim(-0.004, 0.04)\n",
    "\n",
    "plt.ylabel(y_label)\n",
    "\n",
    "plt.xlabel(x_label)\n",
    "\n",
    "plt.title('');\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's take random samples and look at the probability distribution of the sample mean. As usual, we will use simulation to get an empirical approximation to this distribution.\n",
    "\n",
    "We will define a function `simulate_sample_mean` to do this, because we are going to vary the sample size later. The arguments are the name of the table, the label of the column containing the variable, the sample size, and the number of simulations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"Empirical distribution of random sample means\"\"\"\n",
    "\n",
    "def simulate_sample_mean(table, label, sample_size, repetitions):\n",
    "    \n",
    "    means = make_array([])\n",
    "\n",
    "    for i in range(repetitions):\n",
    "        new_sample = table.sample(sample_size)\n",
    "        new_sample_mean = np.mean(new_sample.column(label))\n",
    "        means = np.append(means, new_sample_mean)\n",
    "\n",
    "    sample_means = Table().with_column('Sample Means', means)\n",
    "    \n",
    "    # Display empirical histogram and print all relevant quantities\n",
    "    sample_means.hist(bins=20)\n",
    "    plots.xlabel('Sample Means')\n",
    "    plots.title('Sample Size ' + str(sample_size))\n",
    "    print(\"Sample size: \", sample_size)\n",
    "    print(\"Population mean:\", np.mean(table.column(label)))\n",
    "    print(\"Average of sample means: \", np.mean(means))\n",
    "    print(\"Population SD:\", np.std(table.column(label)))\n",
    "    print(\"SD of sample means:\", np.std(means))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"Empirical distribution of random sample means\"\"\"\n",
    "\n",
    "def simulate_sample_mean(table, label, sample_size, repetitions, xlim=(), ylim=()):\n",
    "    \n",
    "    means = np.array([])\n",
    "\n",
    "    for i in range(repetitions):\n",
    "        new_sample = table.sample(sample_size, replace=True)\n",
    "        new_sample_mean = np.mean(new_sample[label])\n",
    "        means = np.append(means, new_sample_mean)\n",
    "\n",
    "    sample_means = pd.DataFrame({'Sample Means':means})\n",
    "    \n",
    "    # Display empirical histogram and print all relevant quantities\n",
    "\n",
    "    unit = ''\n",
    "\n",
    "    fig, ax = plt.subplots(figsize=(8,5))\n",
    "\n",
    "    ax.hist(sample_means, bins=(20), density=True, color='blue', alpha=0.8, ec='white', zorder=5)\n",
    "\n",
    "    y_label = 'Percent per ' + (unit if unit else 'unit')\n",
    "\n",
    "    x_label = 'Sample Means'\n",
    "    \n",
    "    plt.xlim(xlim)\n",
    "    \n",
    "    plt.ylim(ylim)\n",
    "    \n",
    "    y_vals = ax.get_yticks()\n",
    "\n",
    "    ax.set_yticklabels(['{:g}'.format(x * 100) for x in y_vals])\n",
    "\n",
    "    plt.ylabel(y_label)\n",
    "\n",
    "    plt.xlabel(x_label)\n",
    "\n",
    "    plt.title('Sample Size ' + str(sample_size))\n",
    "\n",
    "    print(\"Sample size: \", sample_size)\n",
    "    print(\"Population mean:\", np.mean(table[label]))\n",
    "    print(\"Average of sample means: \", np.mean(means))\n",
    "    print(\"Population SD:\", np.std(table[label]))\n",
    "    print(\"SD of sample means:\", np.std(means))\n",
    "\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us simulate the mean of a random sample of 100 delays, then of 400 delays, and finally of 625 delays. We will perform 10,000 repetitions of each of these process. The `xlim` and `ylim` lines set the axes consistently in all the plots for ease of comparison. If we knew that the limits would not change we could set the limits as default values in teh function `simulate_sample_mean`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sample size:  100\n",
      "Population mean: 16.658155515370705\n",
      "Average of sample means:  16.68989\n",
      "Population SD: 39.48019985160957\n",
      "SD of sample means: 3.9832359769288086\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 20560 characters]\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "simulate_sample_mean(delay, 'Delay', 100, 10000, (5,35), (0, 0.25))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sample size:  400\n",
      "Population mean: 16.658155515370705\n",
      "Average of sample means:  16.68210625\n",
      "Population SD: 39.48019985160957\n",
      "SD of sample means: 1.9733464148714328\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 20804 characters]\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "simulate_sample_mean(delay, 'Delay', 400, 10000, (5,35), (0, 0.25))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sample size:  625\n",
      "Population mean: 16.658155515370705\n",
      "Average of sample means:  16.640637920000003\n",
      "Population SD: 39.48019985160957\n",
      "SD of sample means: 1.5679866294436549\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 21068 characters]\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "simulate_sample_mean(delay, 'Delay', 625, 10000, (5,35), (0, 0.25))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can see the Central Limit Theorem in action – the histograms of the sample means are roughly normal, even though the histogram of the delays themselves is far from normal.\n",
    "\n",
    "You can also see that each of the three histograms of the sample means is centered very close to the population mean. In each case, the \"average of sample means\" is very close to 16.66 minutes, the population mean. Both values are provided in the printout above each histogram. As expected, the sample mean is an unbiased estimate of the population mean."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The SD of All the Sample Means\n",
    "You can also see that the histograms get narrower, and hence taller, as the sample size increases. We have seen that before, but now we will pay closer attention to the measure of spread.\n",
    "\n",
    "The SD of the population of all delays is about 40 minutes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "39.48019985160957"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pop_sd = np.std(delay['Delay'])\n",
    "pop_sd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Take a look at the SDs in the sample mean histograms above. In all three of them, the SD of the population of delays is about 40 minutes, because all the samples were taken from the same population.\n",
    "\n",
    "Now look at the SD of all 10,000 sample means, when the sample size is 100. That SD is about one-tenth of the population SD. When the sample size is 400, the SD of all the sample means is about one-twentieth of the population SD. When the sample size is 625, the SD of the sample means is about one-twentyfifth of the population SD.\n",
    "\n",
    "It seems like a good idea to compare the SD of the empirical distribution of the sample means to the quantity \"population SD divided by the square root of the sample size.\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here are the numerical values. For each sample size in the first column, 10,000 random samples of that size were drawn, and the 10,000 sample means were calculated. The second column contains the SD of those 10,000 sample means. The third column contains the result of the calculation \"population SD divided by the square root of the sample size.\"\n",
    "\n",
    "The cell takes a while to run, as it's a large simulation. But you'll soon see that it's worth the wait."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "repetitions = 10000\n",
    "sample_sizes = np.arange(25, 626, 25)\n",
    "\n",
    "sd_means = np.array([])\n",
    "\n",
    "for n in sample_sizes:\n",
    "    means = np.array([])\n",
    "    for i in np.arange(repetitions):\n",
    "        means = np.append(means, np.mean(delay['Delay'].sample(n, replace=True)))\n",
    "    sd_means = np.append(sd_means, np.std(means))\n",
    "\n",
    "sd_comparison = pd.DataFrame(\n",
    "    {'Sample Size n':sample_sizes,\n",
    "    'SD of 10,000 Sample Means':sd_means,\n",
    "    'pop_sd/sqrt(n)':pop_sd/np.sqrt(sample_sizes)}\n",
    ")"
   ]
  },
  {
   "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>Sample Size n</th>\n",
       "      <th>SD of 10,000 Sample Means</th>\n",
       "      <th>pop_sd/sqrt(n)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>25</td>\n",
       "      <td>8.035955</td>\n",
       "      <td>7.896040</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>50</td>\n",
       "      <td>5.607407</td>\n",
       "      <td>5.583343</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>75</td>\n",
       "      <td>4.592538</td>\n",
       "      <td>4.558781</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>100</td>\n",
       "      <td>3.977641</td>\n",
       "      <td>3.948020</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>125</td>\n",
       "      <td>3.534429</td>\n",
       "      <td>3.531216</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>150</td>\n",
       "      <td>3.222688</td>\n",
       "      <td>3.223545</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>175</td>\n",
       "      <td>3.016842</td>\n",
       "      <td>2.984423</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>200</td>\n",
       "      <td>2.808212</td>\n",
       "      <td>2.791672</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>225</td>\n",
       "      <td>2.667100</td>\n",
       "      <td>2.632013</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>250</td>\n",
       "      <td>2.510093</td>\n",
       "      <td>2.496947</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Sample Size n  SD of 10,000 Sample Means  pop_sd/sqrt(n)\n",
       "0             25                   8.035955        7.896040\n",
       "1             50                   5.607407        5.583343\n",
       "2             75                   4.592538        4.558781\n",
       "3            100                   3.977641        3.948020\n",
       "4            125                   3.534429        3.531216\n",
       "5            150                   3.222688        3.223545\n",
       "6            175                   3.016842        2.984423\n",
       "7            200                   2.808212        2.791672\n",
       "8            225                   2.667100        2.632013\n",
       "9            250                   2.510093        2.496947"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sd_comparison.head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The values in the second and third columns are very close. If we plot each of those columns with the sample size on the horizontal axis, the two graphs are essentially indistinguishable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 39560 characters]\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "unit = ''\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(8,5))\n",
    "\n",
    "ax.plot(sd_comparison['Sample Size n'], sd_comparison[['SD of 10,000 Sample Means']],\n",
    "       label=['SD of 10,000 Sample Means'], lw=5\n",
    "        , color='gold', zorder=10)\n",
    "\n",
    "ax.plot(sd_comparison['Sample Size n'], sd_comparison[['pop_sd/sqrt(n)']],\n",
    "       label=['pop_sd/sqrt(n)'], alpha=0.2, color='red', zorder=10)\n",
    "\n",
    "x_label = 'Sample Size n'\n",
    "\n",
    "y_vals = ax.get_yticks()\n",
    "\n",
    "ax.set_yticklabels(['{:g}'.format(x * 100) for x in y_vals])\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\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There really are two curves there. But they are so close to each other that it looks as though there is just one.\n",
    "\n",
    "What we are seeing is an instance of a general result. Remember that the graph above is based on 10,000 replications for each sample size. But there are many more than 10,000 samples of each size. The probability distribution of the sample mean is based on the means of *all possible samples* of a fixed size.\n",
    "\n",
    "**Fix a sample size.** If the samples are drawn at random with replacement from the population, then\n",
    "\n",
    "$$\n",
    "{\\mbox{SD of all possible sample means}} ~=~\n",
    "\\frac{\\mbox{Population SD}}{\\sqrt{\\mbox{sample size}}}\n",
    "$$\n",
    "\n",
    "This is the standard deviation of the averages of all the possible samples that could be drawn. **It measures roughly how far off the sample means are from the population mean.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Central Limit Theorem for the Sample Mean\n",
    "If you draw a large random sample with replacement from a population, then, regardless of the distribution of the population, the probability distribution of the sample mean is roughly normal, centered at the population mean, with an SD equal to the population SD divided by the square root of the sample size."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Accuracy of the Sample Mean\n",
    "The SD of all possible sample means measures how variable the sample mean can be. As such, it is taken as a measure of the accuracy of the sample mean as an estimate of the population mean. The smaller the SD, the more accurate the estimate.\n",
    "\n",
    "The formula shows that:\n",
    "- The population size doesn't affect the accuracy of the sample mean. The population size doesn't appear anywhere in the formula.\n",
    "- The population SD is a constant; it's the same for every sample drawn from the population. The sample size can be varied. Because the sample size appears in the denominator, the variability of the sample mean *decreases* as the sample size increases, and hence the accuracy increases."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Square Root Law\n",
    "From the table of SD comparisons, you can see that the SD of the means of random samples of 25 flight delays is about 8 minutes. If you multiply the sample size by 4, you'll get samples of size 100. The SD of the means of all of those samples is about 4 minutes. That's smaller than 8 minutes, but it's not 4 times as small; it's only 2 times as small. That's because the sample size in the denominator has a square root over it. The sample size increased by a factor of 4, but the SD went down by a factor of $2 = \\sqrt{4}$. In other words, the accuracy went up by a factor of $2 = \\sqrt{4}$.\n",
    "\n",
    "In general, when you multiply the sample size by a factor, the accuracy of the sample mean goes up by the square root of that factor.\n",
    "\n",
    "So to increase accuracy by a factor of 10, you have to multiply sample size by a factor of 100. Accuracy doesn't come cheap!"
   ]
  }
 ],
 "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.6.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
