Skip to content

Instantly share code, notes, and snippets.

@AustinRochford
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AustinRochford/53114977dc0697fc9985 to your computer and use it in GitHub Desktop.
Save AustinRochford/53114977dc0697fc9985 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For all the hype about big data, much value resides in the world's medium and small data. Especially when we consider the length of the feedback loop and total analyst time invested, insights from small and medium data are quite attractive and economical. Personally, I find analyzing data that fits into memory quite convenient, and therefore, when I am confronted with a data set that does not fit in memory as-is, I am willing to spend a bit of time to try to manipulate it to fit into memory.\n",
"\n",
"The first technique I usually turn to is to only store distinct rows of a data set, along with the count of the number of times that row appears in the data set. This technique is fairly simple to implement, especially when the data set is generated by a SQL query. If the initial query that generates the data set is\n",
"\n",
"```SQL\n",
"SELECT u, v, w FROM t;\n",
"```\n",
"\n",
"we would modify it to become\n",
"\n",
"```SQL\n",
"SELECT u, v, w, COUNT(1) FROM t GROUP BY u, v, w;\n",
"```\n",
"\n",
"We now generate a sample data set with both discrete and continuous features."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from __future__ import division"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from matplotlib import pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"from patsy import dmatrices, dmatrix\n",
"import scipy as sp\n",
"import seaborn as sns\n",
"from statsmodels import api as sm\n",
"from statsmodels.base.model import GenericLikelihoodModel"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"np.random.seed(1545721) # from random.org"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"N = 100001"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"u_min, u_max = 0, 100"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"v_p = 0.6"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"n_ws = 50\n",
"\n",
"ws = sp.stats.norm.rvs(0, 1, size=n_ws)\n",
"w_min, w_max = ws.min(), ws.max()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"df = pd.DataFrame({\n",
" 'u': np.random.randint(u_min, u_max, size=N),\n",
" 'v': sp.stats.bernoulli.rvs(v_p, size=N),\n",
" 'w': np.random.choice(ws, size=N, replace=True)\n",
" })"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>97</td>\n",
" <td>0</td>\n",
" <td>0.537397</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>79</td>\n",
" <td>1</td>\n",
" <td>1.536383</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>44</td>\n",
" <td>1</td>\n",
" <td>1.074817</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>51</td>\n",
" <td>0</td>\n",
" <td>-0.491210</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>47</td>\n",
" <td>1</td>\n",
" <td>1.592646</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w\n",
"0 97 0 0.537397\n",
"1 79 1 1.536383\n",
"2 44 1 1.074817\n",
"3 51 0 -0.491210\n",
"4 47 1 1.592646"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that this data frame has just over 100,000 rows, but only about 10,000 distinct rows."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"100001"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.shape[0]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"9997"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.drop_duplicates().shape[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now use `pandas`' `groupby` method to produce a data frame that contains the count of each unique combination of `x`, `y`, and `z`."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"count_df = df.groupby(list(df.columns)).size()\n",
"count_df.name = 'count'\n",
"count_df = count_df.reset_index()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order to make later examples interesting, we shuffle the rows of the reduced data frame, because `pandas` automatically sorts the values we grouped on in the reduced data frame."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"shuffled_ixs = count_df.index.values\n",
"np.random.shuffle(shuffled_ixs)\n",
"count_df = count_df.iloc[shuffled_ixs].copy().reset_index(drop=True)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" <th>count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0.425597</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>48</td>\n",
" <td>1</td>\n",
" <td>-0.993981</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>35</td>\n",
" <td>0</td>\n",
" <td>0.358156</td>\n",
" <td>9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>19</td>\n",
" <td>1</td>\n",
" <td>-0.760298</td>\n",
" <td>17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>40</td>\n",
" <td>1</td>\n",
" <td>-0.688514</td>\n",
" <td>13</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w count\n",
"0 0 0 0.425597 14\n",
"1 48 1 -0.993981 7\n",
"2 35 0 0.358156 9\n",
"3 19 1 -0.760298 17\n",
"4 40 1 -0.688514 13"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"count_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, we see that we are storing 90% fewer rows. Although this data set has been artificially generated, I have seen space savings of up to 98% when applying this technique to real-world data sets."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.0999690003099969"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"count_df.shape[0] / N"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This space savings allows me to analyze data sets which initially appear too large to fit in memory. For example, the computer I am writing this on has 16 GB of RAM. At a 90% space savings, I can comfortably analyze a data set that might otherwise be 80 GB in memory while leaving a healthy amount of memory for other processes. To me, the convenience and tight feedback loop that come with fitting a data set entirely in memory are hard to overstate.\n",
"\n",
"As nice as it is to fit a data set into memory, it's not very useful unless we can still analyze it. The rest of this post will show how we can perform standard operations on these summary data sets.\n",
"\n",
"For convenience, we will separate the feature columns from the count columns."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"summ_df = count_df[['u', 'v', 'w']]\n",
"n = count_df['count']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Mean\n",
"\n",
"Suppose we have a group of numbers $x_1, x_2, \\ldots, x_n$. Let the unique values among these numbers be denoted $z_1, z_2, \\ldots, z_m$ and let $n_j$ be the number of times $z_j$ apears in the original group. The mean of the $x_i$s is therefore\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"\\bar{x}\n",
" & = \\frac{1}{n} \\sum_{i = 1}^n x_i\n",
" = \\frac{1}{n} \\sum_{j = 1}^m n_j z_j,\n",
"\\end{align*}\n",
"$$\n",
"\n",
"since we may group identical $x_i$s into a single summand. Since $n = \\sum_{j = 1}^m n_j$, we can calculate the mean using the following function."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def mean(df, count):\n",
" return df.mul(count, axis=0).sum() / count.sum()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"u 49.308067\n",
"v 0.598704\n",
"w 0.170815\n",
"dtype: float64"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mean(summ_df, n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the means calculated by our function agree with the means of the original data frame."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"u 49.308067\n",
"v 0.598704\n",
"w 0.170815\n",
"dtype: float64"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.mean(axis=0)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.allclose(mean(summ_df, n), df.mean(axis=0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Variance\n",
"\n",
"We can calculate the variance as\n",
"\n",
"$$\n",
"\\begin{align*}\n",
" \\sigma_x^2\n",
" & = \\frac{1}{n - 1} \\sum_{i = 1}^n \\left(x_i - \\bar{x}\\right)^2\n",
" = \\frac{1}{n - 1} \\sum_{j = 1}^m n_j \\left(z_j - \\bar{x}\\right)^2\n",
"\\end{align*}\n",
"$$\n",
"\n",
"using the same trick of combining identical terms in the original sum. Again, this calculation is easy to implement in Python."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def var(df, count):\n",
" mu = mean(df, count)\n",
" \n",
" return np.power(df - mu, 2).mul(count, axis=0).sum() / (count.sum() - 1)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"u 830.025064\n",
"v 0.240260\n",
"w 1.099191\n",
"dtype: float64"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"var(summ_df, n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the variances calculated by our function agree with the variances of the original data frame."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"u 830.025064\n",
"v 0.240260\n",
"w 1.099191\n",
"dtype: float64"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.var()"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.allclose(var(summ_df, n), df.var(axis=0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Histogram\n",
"\n",
"Histograms are fundamental tools for exploratory data analysis. Fortunately, `pyplot`'s [`hist`](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist) function easily accommodates summarized data using the `weights` optional argument."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA8YAAAGMCAYAAAAYzbviAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3X1clfXh//H34UZU0EhBKJ31VTatHN5GeRMkGoqkgdrN\nNil107HmzLxpUfrDtsyv687cZpNR2dpa5UidYdPUxFym2SZm1mPRDWrCOUiSiiJ31+8Pv50JguDx\n3OHn9Xw8ejziOtfN+/qcIx/enIvr2CzLsgQAAAAAgKECfB0AAAAAAABfohgDAAAAAIxGMQYAAAAA\nGI1iDAAAAAAwGsUYAAAAAGA0ijEAAAAAwGgUY8BPHTp0SL1791ZdXZ0kKT09XatWrWrRtjt37lRC\nQoIn49Xz8ssva8iQIRowYIC++eYbrx0XAAB/NG3aNK1Zs8at+/ztb3+refPmtXj93r176+DBg27N\n0JQPPvhASUlJ6t+/vzZv3uyVYwLuFuTrAIAJEhMTVVZWpoCAM7+Lstls2rBhgyIjIy9oPzabze3Z\nXn/9df3tb3/Tyy+/7NL21dXVWrJkiVatWqXvfe97bk4HADDF7t279cQTT6iwsFCBgYHq0aOHHnro\nIX3/+9/3dbQL9sc//tHt+/TEzwDSmV/Ejxw5Uvv373f+nHKhli1bpvT0dKWnp7s5HeA9FGPAS/7w\nhz9o8ODBvo7hdkeOHNHp06fVs2fPRh+vqalRUBDfagAATTtx4oQyMjL0q1/9SsnJyaqqqtLu3bvV\npk0bX0e7IJZlSfJcifWkb7O7ori4WDExMefdb2scE5iFS6kBH0pMTNSOHTucX1/oZVLfqqys1IMP\nPqi4uDilpKToww8/rPd4dna2brnlFg0YMEApKSnatGmTJOmzzz7TwoULtWfPHvXv319xcXGSpK1b\ntyo1NVUDBw7UzTffrN/97neNHveLL77QmDFjJEmDBg3S5MmTJZ25fOsvf/mLkpKSNHr0aEnSo48+\nqptvvlkDBw7U+PHjtXv37nrnPXPmTM2bN08DBgzQ2LFj9eWXX2rFihUaMmSIhg8frn/+85/O9Y8f\nP66HHnpIw4YNU3x8vJYuXeq85BwA0Pp88cUXstlsGjNmjGw2m0JCQjR06FD16tVL0rnzY2N/brR0\n6VLddddd6t+/vzIyMvT1119rzpw5GjhwoCZOnKivvvrKuX3v3r318ssvKykpSQMGDNAzzzyjAwcO\n6M4779SgQYN0//33q7q6WpJ07Ngx/fSnP9XgwYMVFxenjIwM2e12577S09P19NNPO4998ODBen/+\nNG7cOPXv39/5X+/evfX+++9Lkvbs2aO77rpL119/vW677Tbt2rXLud+DBw9q0qRJGjBggKZOnaqj\nR4+edwxzcnKc8+Lf/va3eo+db16fNGmSpDPzeP/+/VVQUKADBw7o7rvv1g033KAbb7xRc+fO1fHj\nxxs97siRI3Xw4EFlZGRowIABqqqqqjcm/fr108GDB5Wbm6sxY8ZowIABGjlypF599VXnPnbu3Kn4\n+Hjl5ORo8ODBGjZsmDZt2qT8/HyNGjVKN9xwg7Kzs53rW5bl/Nnmhhtu0KxZs/hTLlw8C4DHDR8+\n3Hr33XebXf7b3/7Wmjt3rmVZlnXw4EGrV69eVm1trWVZljVp0iRr1apVje7/8ccft370ox9Z33zz\njVVcXGylpKRYCQkJzsfffPNNy+FwWJZlWXl5eVa/fv2s0tJSy7Is6/XXX7d+8IMf1Nvfzp07rf/8\n5z+WZVnWJ598Yg0ZMsR66623Gj32oUOH6uW0LMvq1auXNXXqVOubb76xTp8+bVmWZa1du9YqLy+3\namtrreeff94aOnSo87Fly5ZZ3//+963t27dbNTU11gMPPGANHz7c+sMf/mDV1NRYr732mpWYmOjc\n/7333mv9v//3/6xTp05ZZWVl1sSJE61XXnml0XwAAP93/PhxKy4uzvrlL39p5efnW+Xl5fUeP3t+\ntKzG58ikpCTrwIED1vHjx60xY8ZYt9xyi/Xuu+8655UHH3zQuX2vXr2se++91zpx4oT16aefWtdd\nd52Vnp5uHTx40Ln96tWrLcuyrKNHj1obN260KisrrRMnTlgzZ8607r33Xue+Jk2aZA0fPtwqLCy0\namtrrerq6ibn7FdeecVKTk62Tpw4YZWUlFhxcXFWfn6+ZVmW9c9//tOKi4uzvv76a8uyLOuOO+6w\n/vd//9eqqqqy3n//fat///7WvHnzGh2//Px8a8iQIdann35qnTx50po9e7bVq1cv68CBA5ZlnX9e\nb2weLyoqst59912rqqrKKisrs370ox9ZixYtavL5a/jzTGNjsnXrVmeeXbt2WX379rU++ugjy7Is\n67333rOuvfZa6/e//71z3o+Li7Nmz55tVVRUWJ9++qkVGxtrHTp0yLIsy1q5cqV15513WiUlJVZV\nVZW1YMECa/bs2U3mA1qCd4wBL7n33nt1/fXX6/rrr9eMGTMaXcdy8TKmf/zjH8rIyFDHjh0VHR2t\nu+++u96+Ro8e7fx75jFjxuiqq65SQUFBk8eMi4vTd7/7XUlSr169NGbMGOdvt1uaefr06erYsaPz\nMrhx48bpsssuU0BAgKZMmaKqqip98cUXzvWvv/56DR06VIGBgRo1apSOHj2q6dOnKzAwUMnJyfrq\nq6904sQJHTlyRNu2bdNDDz2ktm3bqlOnTrrnnnuUl5fnwsgBAPxBWFiYXn75ZdlsNi1YsEBDhgzR\nz372M5WVlUlq2fw4fvx4fec731FYWJji4+N19dVXa/DgwQoMDNTo0aP18ccf11v/Jz/5iUJDQxUT\nE6Pvfe97io+PV7du3Zzb79+/X5IUHh6uW265RSEhIQoNDVVGRsY5c2JaWpp69uypgICAJv98aPfu\n3XrmmWf07LPPKjQ0VGvXrlVCQoLi4+MlSUOGDFGfPn2Un5+vw4cPa9++fbrvvvsUHBysQYMGafjw\n4U2Ow5tvvqkJEyYoJiZG7dq10y9+8Yt6j59vXm9sn927d9fgwYMVHBysTp06afLkyU3+HNCUhmOS\nkJCg73znO5L+O+efffVYUFCQfvaznznn/W+++Ub33HOP2rdvr5iYGPXs2VOffPKJJOmVV17Rfffd\np6ioKAUHB2vGjBnasGEDV4/hovCHf4CXLF++3GN/Y+xwOHTFFVc4vz77/yVpzZo1WrlypfMyspMn\nT6q8vLzJ/RUUFDhvgFJdXa2qqiolJydfUKaGGZ577jnl5ubK4XDIZrPpxIkT9S4L69Spk/P/27Zt\nq8svv9z590ht27aVJFVUVMhut6umpkbDhg1zrl9XV6crr7zygvIBAPxLz549tXjxYknS559/rnnz\n5umxxx7Tk08+2aLtO3fu7Pz/Nm3a1Ps6JCREJ0+erLd+RESE8//btm1b7+uQkBAdOXJEknTq1Ckt\nXrxY27dvd16ue/LkSVmW5ZynoqOjz5utuLhY999/v5YsWaKrrrpKknT48GH94x//0Ntvv+1cr6am\nRjfeeKMcDoc6duzonP8kqWvXriouLm50/6WlpfVuUtZwTrzQef3IkSNatGiRPvjgA1VUVKiurk7h\n4eHnPceGGo5Jfn6+fv/736uoqEh1dXU6deqU81J56cwvIBrO+w2fo2+fw8OHD2vGjBn1bhYWGBio\nI0eOqEuXLheUE/gWxRjwofbt2+vUqVPOr0tLS13aT2RkpA4fPuy8AdbZE+dXX32lBQsW6MUXX1T/\n/v1ls9mUmpp63pthzJkzR+np6XruuefUpk0bPfbYY83+bVNDZ+939+7deu655/Tiiy86f2MdFxfn\n0jvk0dHRatOmjXbu3Ony3TMBAP6tR48eSktLc/4dart27VRZWel8/NvS2hR33ujp+eef1xdffKFV\nq1apc+fO+vjjj5WWllavGJ/veJWVlfr5z3+uyZMn66abbnIuv/LKK3Xbbbfp17/+9TnbfPXVVzp2\n7JhOnTqldu3aOZcFBgY2eozIyMh6c//hw4frPX6+eb2x7E899ZQCAgL0xhtvqGPHjtq0aVOjOc/n\n7P1WVVVp5syZevzxxzVixAgFBgbq5z//uctXyl1xxRVavHix+vfv79L2QGP4qRLwod69eysvL081\nNTX68MMPtXHjxvNOrk1NIMnJycrOztaxY8dUUlKil156yfnYqVOnZLPZdPnll6uurk65ubn69NNP\nnY937txZJSUlzpuMSGd+E37ZZZepTZs22rt3r954442L+iGjoqJCgYGBuvzyy1VVVaXf/e53OnHi\nhEv76tKli4YOHarFixfrxIkTqqur04EDBy74Ei8AgP/4/PPP9cILLzhvalVcXKw33njDWXyuueYa\nvf/++youLtbx48e1YsWKc/Zx9hzpSuFqavuTJ0+qbdu26tChg8rLyxu9IeX5jvfQQw+pR48e+vGP\nf1xv+bhx4/T2229r+/btqq2t1enTp7Vz507Z7XZ17dpVffr00bJly1RdXa3du3dr69atTR4jOTlZ\nq1ev1meffaZTp06dk/F883qnTp0UEBCgAwcO1Fu/ffv2CgsLk91uV05OTpPHbsrZY1JVVaXq6mpd\nfvnlCggIUH5+fr2bal6ou+66S0899ZTzFwBff/01n5+Mi0YxBnzovvvu08GDB3X99dfrd7/7ncaO\nHVvv8YZltKlyOmPGDF155ZUaMWKEfvKTnyg1NdW5bkxMjKZMmaK77rpLQ4cO1aeffqoBAwY4tx08\neLC++93vatiwYc5LvbOysrRs2TINGDBAy5cvd955uinN5bzpppt00003adSoUUpMTFTbtm3rXWpt\ns9ma3cfZX//mN79RdXW1UlJSFBcXp/vuu8/ld9sBAL4XGhqqgoIC3X777erfv7/uvPNO9erVS7/8\n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\nrbfqT3/6U6Pr+dNYtySzP461v2Ju9g7mZs9ibvYO5mbvYG7+P9YlbPv27VZtba1lWZb1+OOPW48/\n/vg569TU1FgjR460Dh48aFVVVVnjxo2zCgsLvR3VqbCw0Pr888+tSZMmWfv27WtyveHDh1tHjx71\nYrKmtSSzv43zkiVLrOzsbMuyLGvFihWNvjYsy/fj3JJx27p1q/WTn/zEsizL2rNnj3X77bf7IqpT\nSzK/99571k9/+lMfJWzc+++/b3300UfWrbfe2ujj/jbOltV8Zn8cZ4fDYe3fv9+yLMs6ceKElZSU\n5Pev6ZZk9sex9lfMzd7B3Ow5zM3ew9zsHczNZ1zS7xgPHTpUAQFnTrFv374qKSk5Z529e/eqe/fu\n6tatm4KDg5WSkqLNmzd7O6pTz5499T//8z8tWtfykxuKtySzv43zli1blJaWJklKS0vTpk2bmlzX\nl+PcknHbvHmz81z69u2rY8eO6ciRI76IK8n/nuuWGjRokDp27Njk4/42zlLzmf1RZGSkrrnmGklS\naGioevbsKYfDUW8dfxvrlmRGyzE3ewdzs+cwN3sPc7N3MDefcUkX47Pl5uYqISHhnOV2u11XXHGF\n8+uoqCjZ7XZvRnOJzWbTlClTNH78eL322mu+jtMsfxvnsrIyRURESJIiIiJUVlbW6Hq+HueWjJvD\n4VB0dLTz6+jo6EZ/0PSWlmS22Wz697//rXHjxmnatGkqLCz0dswL5m/j3BL+Ps6HDh3Sxx9/rNjY\n2HrL/Xmsm8rs72Ptr5ibfcvfxpm52XOYm/2Hv4+zyXNzkCdDesOUKVMa/W3F/fffr8TEREnSs88+\nq+Dg4Eav9bfZbB7P2FBLMjfnr3/9q7p06aKvv/5aU6ZMUY8ePTRo0CB3R3W62Mz+NM6zZs2q97XN\nZmsyn7fHuaGWjlvD35z7Yrwv5NjXXnuttm7dqnbt2ik/P18///nPtWHDBi+kuzj+NM4t4c/jXFFR\noZkzZ+rhhx9WaGjoOY/741ifL7M/j7UvMDczNzeFudk3mJv9hz+Ps+lzc6svxi+88MJ5H3/99deV\nn5+vF198sdHHo6KiVFxc7Py6pKREUVFRbs3YUHOZW6JLly6SpE6dOumWW27R3r17PTopXGxmfxvn\nzp07q7S0VJGRkXI4HOrUqVOj63l7nBtqybh16dKl3m/svDG259OSzGFhYc7/T0hI0COPPKLy8nKF\nh4d7LeeF8rdxbgl/Hefq6mrNnDlT48aN08iRI8953B/HurnM/jrWvsLczNzcFOZm32Bu9h/+Os7M\nzZf4pdTbtm3Tc889p+XLlyskJKTRdfr06aOioiIdOnRIVVVVWr9+vUaMGOHlpI1r6u9nTp06pRMn\nTkiSTp48qe3bt+t73/ueN6M1qanM/jbOiYmJWr16tSRpzZo1jf5j8odxbsm4jRgxQmvWrJEk7dmz\nRx07dnReiuYLLcl85MgR52tl7969kuTzCaE5/jbOLeGP42xZlh5++GH17NlTkydPbnQdfxvrlmT2\nx7H2V8zN3sfc7F7Mzf7D38a5JfxxnJmbz7BZ/nKXCA9ISkpSdXW1LrvsMklSv379tHDhQtntdi1Y\nsMB5q/r8/Hw99thjqqur08SJE/XTn/7UZ5nfeustPfroozp69Kg6dOiga665Rjk5OfUyHzx4UDNm\nzJAk1dbWauzYsX6fWfKvcS4vL9esWbNUXFysrl27aunSperYsaNfjnNj4/bKK69Iku666y5J0q9+\n9Su98847ateunRYvXqzrrrvO6znP1lzmv/zlL/rrX/+qwMBAtWvXTg8++KD69evn08yzZ8/Wrl27\nVF5ers6dO+sXv/iFampqnJkl/xvn5jL74zjv3r1bkyZNUq9evZyXYN1///3OdzL8caxbktkfx9pf\nMTf7T2bJv8aZudmzmJu9g7nZfzJf6Fhf0sUYAAAAAIDmXNKXUgMAAAAA0ByKMQAAAADAaBRjAAAA\nAIDRKMYAAAAAAKNRjAEAAAAARqMYAwAAAACMRjEGAAAAABiNYgwAAAAAMBrFGAAAAABgtCBfBwDg\ne4WFhfrggw90+vRp3X333VqyZInuvPNO7dixQwEBAbrzzjt9HREAAKMwNwPexTvGAFRWVqbIyEhV\nV1dLkvbs2aOrr75at9xyi4+TAQBgJuZmwLsoxgB0ww03KC8vT8nJyTp69Kguu+wySdKpU6c0cOBA\nH6cDAMA8zM2Ad1GMAUiS7Ha7rrzySv3nP/9Rjx49JEn/+c9/FBMT4+NkAACYibkZ8J7AhQsXLvR1\nCAC+V1paqsOHD+ubb75RcXGxTp8+rejoaEVFRfk6GgAARmJuBrzHZlmW5esQAAAAAAD4CpdSAwAA\nAACMRjEGAAAAABiNYgwAAAAAMBrFGAAAAABgNIoxAAAAAMBoFGMAAAAAgNEoxgAAAAAAo1GMAQAA\nAABG+/++j1itpPe7HAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f24fc5f6e50>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, (full_ax, summ_ax) = plt.subplots(ncols=2, sharex=True, sharey=True, figsize=(16, 6))\n",
"\n",
"nbins = 20\n",
"\n",
"blue, green = sns.color_palette()[:2]\n",
"\n",
"full_ax.hist(df.w, bins=nbins, color=blue, alpha=0.5, lw=0);\n",
"full_ax.set_xlabel('$w$');\n",
"full_ax.set_ylabel('Count');\n",
"full_ax.set_title('Full data frame');\n",
"\n",
"summ_ax.hist(summ_df.w, bins=nbins, weights=n, color=green, alpha=0.5, lw=0);\n",
"summ_ax.set_xlabel('$w$');\n",
"summ_ax.set_title('Summarized data frame');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the histograms for $w$ produced from the full and summarized data frames are identical."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Quantiles\n",
"\n",
"Calculating the mean and variance of our summarized data frames was not too difficult. Calculating quantiles from this data frame is slightly more involved, though still not terribly hard.\n",
"\n",
"Our implementation will rely on sorting the data frame. Though this implementation is not optimal from a computation complexity point of view, it is in keeping with the spirit of `pandas`' [implementation of quantiles](https://github.com/pydata/pandas/blob/654e7397280be9a681fafcf8f70cfe3e20a9ef47/pandas/core/algorithms.py#L367). I have given some thought on how to implement [linear time selection](https://en.wikipedia.org/wiki/Median_of_medians) on the summarized data frame, but have not yet worked out the details.\n",
"\n",
"Before writing a function to calculate quantiles of a data frame with several columns, we will walk through the simpler case of computing the quartiles of a single series."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"u = summ_df.u"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0 0\n",
"1 48\n",
"2 35\n",
"3 19\n",
"4 40\n",
"Name: u, dtype: int64"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we [`argsort`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.argsort.html) the series."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"sorted_ilocs = u.argsort()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that `u.iloc[sorted_ilocs]` will now be in ascending order."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"sorted_u = u.iloc[sorted_ilocs]"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(sorted_u[:-1] <= sorted_u[1:]).all()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"More importantly, `counts.iloc[sorted_ilocs]` will have the count of the smallest element of `u` first, the count of the second smallest element second, etc."
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"sorted_n = n.iloc[sorted_ilocs]\n",
"sorted_cumsum = sorted_n.cumsum()\n",
"cdf = (sorted_cumsum / n.sum()).values"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, the $i$-th location of `sorted_cumsum` will contain the number of elements of `u` less than or equal to the $i$-th smallest element, and therefore `cdf` is the empirical cumulative distribution function of `u`. The following plot shows that this interpretation is correct."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\n9wvkbBtzj2/jyAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f24fc1a7a90>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(8, 6))\n",
"\n",
"blue, _, red = sns.color_palette()[:3]\n",
"ax.plot(sorted_u, cdf, c=blue, label='Empirical CDF');\n",
"plot_u = np.arange(100)\n",
"ax.plot(plot_u, sp.stats.randint.cdf(plot_u, u_min, u_max), '--', c=red, label='Population CDF');\n",
"\n",
"ax.set_xlabel('$u$');\n",
"\n",
"ax.legend(loc=2);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If, for example, we wish to find the median of `u`, we want to find the first location in `cdf` which is greater than or equal to 0.5."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"median_iloc_in_sorted = (cdf < 0.5).argmin()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The index of the median in `u` is therefore `sorted_ilocs.iloc[median_iloc_in_sorted]`, so the median of `u` is"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"49"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u.iloc[sorted_ilocs.iloc[median_iloc_in_sorted]]"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"49.0"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.u.quantile(0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can generalize this method to calculate multiple quantiles simultaneously as follows."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"q = np.array([0.25, 0.5, 0.75])"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2299 24\n",
"9079 49\n",
"1211 74\n",
"Name: u, dtype: int64"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u.iloc[sorted_ilocs.iloc[np.less.outer(cdf, q).argmin(axis=0)]]"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.25 24\n",
"0.50 49\n",
"0.75 74\n",
"dtype: float64"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.u.quantile(q)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The array `np.less.outer(cdf, q).argmin(axis=0)` contains three columns, each of which contains the result of comparing `cdf` to an element of `q`. The following function generalizes this approach from series to data frames."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def quantile(df, count, q=0.5):\n",
" q = np.ravel(q)\n",
" \n",
" sorted_ilocs = df.apply(pd.Series.argsort)\n",
" sorted_counts = sorted_ilocs.apply(lambda s: count.iloc[s].values)\n",
" cdf = sorted_counts.cumsum() / sorted_counts.sum()\n",
" \n",
" q_ilocs_in_sorted_ilocs = pd.DataFrame(np.less.outer(cdf.values, q).argmin(axis=0).T,\n",
" columns=df.columns)\n",
" q_ilocs = sorted_ilocs.apply(lambda s: s[q_ilocs_in_sorted_ilocs[s.name]].reset_index(drop=True))\n",
" \n",
" q_df = df.apply(lambda s: s.iloc[q_ilocs[s.name]].reset_index(drop=True))\n",
" q_df.index = q\n",
" \n",
" return q_df"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.25</th>\n",
" <td>24</td>\n",
" <td>0</td>\n",
" <td>-0.688514</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.50</th>\n",
" <td>49</td>\n",
" <td>1</td>\n",
" <td>0.040036</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.75</th>\n",
" <td>74</td>\n",
" <td>1</td>\n",
" <td>1.074817</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w\n",
"0.25 24 0 -0.688514\n",
"0.50 49 1 0.040036\n",
"0.75 74 1 1.074817"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quantile(summ_df, n, q=q)"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.25</th>\n",
" <td>24</td>\n",
" <td>0</td>\n",
" <td>-0.688514</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.50</th>\n",
" <td>49</td>\n",
" <td>1</td>\n",
" <td>0.040036</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.75</th>\n",
" <td>74</td>\n",
" <td>1</td>\n",
" <td>1.074817</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w\n",
"0.25 24 0 -0.688514\n",
"0.50 49 1 0.040036\n",
"0.75 74 1 1.074817"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.quantile(q=q)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.allclose(quantile(summ_df, n, q=q), df.quantile(q=q))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Bootstrapping\n",
"\n",
"Another important operation is [bootstrapping](https://en.wikipedia.org/wiki/Bootstrapping_(statistics%29). We will see two ways to perfom bootstrapping on the summary data set."
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"n_boot = 10000"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Key to both approaches to the bootstrap is knowing the proprotion of the data set that each distinct combination of features comprised."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"weights = n / n.sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The two approaches differ in what type of data frame they produce. The first we will discuss produces a non-summarized data frame with non-unique rows, while the second produces a summarized data frame. Each fo these approaches to bootstrapping is useful in different situations."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Non-summarized bootstrap"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To produce a non-summarized data frame, we generate a list of locations in `feature_df` based on `weights` using [`numpy.random.choice`](http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.random.choice.html)."
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"boot_ixs = np.random.choice(summ_df.shape[0], size=n_boot, replace=True,\n",
" p=weights)"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"boot_df = summ_df.iloc[boot_ixs]"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1171</th>\n",
" <td>47</td>\n",
" <td>1</td>\n",
" <td>-1.392235</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9681</th>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" <td>0.018521</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6664</th>\n",
" <td>13</td>\n",
" <td>1</td>\n",
" <td>1.941207</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8343</th>\n",
" <td>13</td>\n",
" <td>0</td>\n",
" <td>0.655181</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3595</th>\n",
" <td>95</td>\n",
" <td>1</td>\n",
" <td>0.972592</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w\n",
"1171 47 1 -1.392235\n",
"9681 3 1 0.018521\n",
"6664 13 1 1.941207\n",
"8343 13 0 0.655181\n",
"3595 95 1 0.972592"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"boot_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can verify that our bootstrapped data frame has (approximately) the same distribution as the original data frame using [Q-Q plots](https://en.wikipedia.org/wiki/Q%E2%80%93Q_plot)."
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"ps = np.linspace(0, 1, 100)"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"boot_qs = boot_df[['u', 'w']].quantile(q=ps)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"qs = df[['u', 'w']].quantile(q=ps)"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\nkvCFEEKIBeBvSOuq+STOyLAAAAAASUVORK5CYII=\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f24fc5f6c90>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(8, 6))\n",
"\n",
"blue = sns.color_palette()[0]\n",
"ax.plot((u_min, u_max), (u_min, u_max), '--', c='k', lw=0.75,\n",
" label='Perfect agreement');\n",
"ax.scatter(qs.u, boot_qs.u, c=blue, alpha=0.5);\n",
"\n",
"ax.set_xlim(u_min, u_max);\n",
"ax.set_xlabel('Original quantiles');\n",
"\n",
"ax.set_ylim(u_min, u_max);\n",
"ax.set_ylabel('Resampled quantiles');\n",
"\n",
"ax.set_title('Q-Q plot for $u$');\n",
"ax.legend(loc=2);"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAfkAAAGOCAYAAACUkXqdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3XlcVFX/B/DPMAMOm6Asg2sphuaGGq2oJCqY4JY+bqiJ\nC6mlZZtl6lOPC25Z/TI1wsztEZdMzSX0kcAllzKTBBVcC2HYhEQF4V7m9wcxggLDMjN3Zvi8Xy9e\nL2fuufd+jwN8OeeeRabRaDQgIiIii2MldQBERERkGEzyREREFopJnoiIyEIxyRMREVkoJnkiIiIL\nxSRPRERkoZjkiYiILBSTPBERkYVikieiGvH398eJEyf0cq2rV69i0KBB6NatGzZt2qSXaxLRA0zy\nRGZk586dGDBgALp06YLu3bvjo48+Ql5ent7P0RddfxBERkbi+eefx2+//YYxY8YYJSai+oRJnshM\nfPPNN/jkk08wa9YsnDlzBlu3bkVqaipCQ0NRVFSkt3OMKTU1FZ6enrU6VxAEPUdDZHmY5InMwJ07\nd/DFF19g7ty56N69O+RyOZo1a4bPPvsMN2/exJ49e/RyTil/f39EREQgKCgIzzzzDD744AMUFhY+\nUu7KlSsYO3Ysnn76aQQHByMmJkZ77N1330VaWhqmTJmCrl27Yu3ateXOHTduHE6fPo358+ejW7du\nuHHjhs5r+vv74+uvv8aAAQPQrVs3FBcX1/j/kqg+YZInMgO//fYbCgsLERAQUO59Ozs7+Pn54eef\nf9bLOWX98MMP+Oabb3Do0CFcv34dq1atKne8qKgIU6ZMQY8ePXDixAnMmTMH77zzDq5duwYAWLZs\nGZo0aYI1a9bg7NmzmDhxYrnzN2zYgKeeegrz5s3Db7/9hscee6zSa16/fl173v79+xEZGYlff/0V\nVlb8FUZUFf6EEJmBnJwcNGrUqMKk5urqitzcXL2cU9aYMWOgUqng5OSEKVOmYN++feWOnzt3Dvn5\n+QgLC4NCocBzzz2HXr16PVJOl7IbYVZ2zb1792rLjB07FiqVCjY2No9cKyUlBQcPHsScOXMAAImJ\niViwYAEA4JVXXsHVq1drFBuRuWOSJzIDjRo1Qk5OToXd05mZmXB1dcUPP/yArl27omvXrggLC0Pj\nxo11nlMVDw8P7b+bNm2KjIyMcsczMjLKlSktl56eXpOqQSaT6bxm2Xs3adKk0mvduHEDbdu21ZY/\nevQoOnToAADo168frK2taxQbkbljkicyA127doWNjQ2io6PLvX/37l0cPXoUvr6+GDBgAM6ePYuz\nZ88iIiICXbp00XlOVdLS0rT/Tk1NhUqlKnfc3d0darW6XEv84XJlE3h1VHZNd3f3ap3v6+uL77//\nHv379wcAnD59Gi+88AIAwMnJCS1atKhRPETmjkmeyAw4Ojritddew4IFC3D06FEUFRUhJSUFb775\nJlq2bKlNanU9p6z//ve/SE9PR25uLtasWYOXXnqp3HFvb28olUp8/fXXKCoqwqlTp/DTTz8hKChI\nW8bV1RV//fVXlfcpm9Crc01dEhMT0bFjRwCAWq2GSqXiSHyqtxRSB0BE1TNp0iQ4Oztj6dKluHHj\nBgoLC9GzZ09ERkZCoaj4R7k255QKDg7GhAkTkJGRgT59+mDatGnljltbW2PNmjX4+OOPERERAQ8P\nDyxduhStWrXSlgkLC8OCBQuwbNkyTJs2DaGhoY/cp2xrvzrX1CU4OBj79+9Hq1at0KNHD+zfvx93\n795FcHBwta9BZClkmrJ/RhOR2di5cyeWL1+OrVu3Vrsburrn+Pv7Y+HChXj++ef1FS4RSYAteSIz\n9fLLL0Mul+PcuXPVTvK1OYeIzBeTPJEZGzRokFHOISLzxO56IiIiC8XR9URERBbK4rrrMzONs7sW\nADRqZIecnHtGu5+xsX7mzZLrZ8l1A1g/c2eM+u3YvR8HT1/HqYMb8Mq7XyH8te4VlrO4JG9MCoVc\n6hAMivUzb5ZcP0uuG8D6mTtD108URVw6fxrn4g5j0MSFEMXKd5Rkdz0REZGZUKvTMGrUUKhUHog9\ndBCdm9yHt6ryHmy25ImIiMzE6tUrMXv2PHTp0g0AMGxQf7i5OVZankmeiIjITHz88cIalWd3PRER\nkYVikiciIjJBoijW+RpM8kRERCZEEAQsXjwfK1d+VudrMckTERGZiNLR8y4urpgx4606X49J3kh6\n9nwGoaGjMW7cCMyd+z7u3y+o0flffvk5xo4djlWr/q/G996w4Zsan2Nu1Oo0HDr0o9RhEBHVWmxs\nDEJDQzB79jxMnjy13DbMtcUkbyQNGiixbt1/sWHDVlhbW2PXru+qdV7pM5kffvgeGzZsxbRpM2p8\n740bv63xOdUhCIJBrlsbqak3cehQtNRhEBHVypEjsdiwYR2ionaia9en9HZdTqGTQOfO3rhy5QoK\nCgqwYsUSXLt2FaIoYMKEMHTv7of9+39AXFwMCgoKIIoiHBwckJ+fjwkTQjBmTCi6dfPBJ5+EIz1d\nDQCYMeNtdOrkjXv37uGzz5bh0qULAGSYMGEyLlxIRGHhfYSGjkbr1p6YO3d+uViWL1+MixcTcf9+\nAV58sTcmTnwVAHDixDGsXv1/sLZugE6dOiM1NRVLl36KtWu/QmpqClJTU+Hh0QRvvPEOli9f9Egs\n+fn5+PTTpRXW7ejRWBQUFCAl5S+MHBmC+/cL8b///QhraxssW/Y5GjZsiJs3U7BixVLk5uZAqVRi\n1qwP0bLl41i48CPY2zvg0qVEZGdnY9q0GXjxxd5Ys2Yl/vzzOkJDR+OllwZg+PBRRv1MiYjqwte3\nB3r08NNL670sJnkjEwQBp06dwLPPvoD169fCx+cZzJ79b+Tl5SEs7BX4+DwLAEhOTsL69VFwdCxZ\n5KBv355Yt+6/AICPPvoQw4ePRufOXaBWq/HOO9OxadN2fPttJBwdHbF+fRQAIC8vD35+/vjuu23a\ncx8WFjYNDRs2hCiKePPNabhy5TKaN2+BZcvCERW1BTY2DfHRRx+i7PfdjRs3sGpVJGxsbCqNZcOG\nbyqt27VrV7Fu3X9x//59jBgxCNOmvYFvvtmML75YgR9/3Ifhw0dh6dKFePfd2WjevAUSEs7jk0+W\n4PPPVwMAbt3KxurV3+D69Wt4//238OKLvTF16nRs2bIJS5d+apDPjYjIkORywyyFyyRvJKWtaQDw\n9u6G4OBBePXVUBw/fgRbtmwEABQVFSE9XQ2ZTAYfn2e0Cf5hv/56GjduXNO+vnfvHvLz83HmzC/4\nz3/Cte9Xdn5ZMTEHsWfPLoiiiOzsLFy/fhXFxSKaNm2GZs2aITMzD336BGLPnu8BADKZDN2794SN\njU2VsZw+fbLSunXt6gNbW1vY2trCwcERvr49AQCtW7fBlSvJyM/Pxx9/xGPu3Fna6xYVCdr79+jh\nBwB4/PFWuHXrFgCAOyYTET2qXib5qKjNiIra/Mj7I0eGYOTIkGqXnzx5IoKChlbrnjY2DSpsTS9c\nuAwtWrQs915i4nnY2tpWcTUNIiLWw9ra+tEjNUh2qak3ERW1GZGRG+Hg4IBFiz5GYWEhgIe7i8pf\ns0EDZbViqaxuNjYPylpZWWlfW1lZQRRFaDTFcHR0rLT3oey9mNyJyJykp6vxn//Mw6efrtQ2lgyp\nXg68GzkyBLt27X/kq6IEX1X58ePH1ymOZ555Djt2RGlfJyVdBKA7cT399HPYvv3BecnJSf+8/yx2\n7tymfT8vr2TTAoVCUeEgubt370KptIW9vT1u3crGyZM/AwBatnwMqak3cfPmTQDA4cOHtN31D8dW\nWSy1qVvpMTs7ezRt2hQ//fQ/7fuXLydXel7pOffu3a2yDBGRlGJjYzB+fAgmTXrVKAkekDDJp6Wl\nYezYsQgKCkJwcDA2bNhQYbkFCxYgICAAAwcORGJiopGj1J+KBlOMHz8JgiDglVdGYuzY4Vi79itt\n2YfLl3395pvv4NKlRLzyyiiMGTMcu3fvBAC88spE5OXlYdy4ERg/fjTOnj0DABg4cAjGjx+F+fPn\nlrvmE094wcurLUaPHoqPP56Lzp29AQANGjTA22+/j0mTJmHixLGwt7eHg4NDmdigM5bq1+3Bv8se\nmzdvAfbu3YPx40dj7NgROHYsrsL/i9J/t2nzBORyOcaPH41t27ZU+BkQEUmhdHGbjRu/RVTUd3od\nPa+LTCNRf2dmZiaysrLw5JNP4u7du3j55ZexatUqeHp6asvExcVh06ZN+Prrr3Hu3DksXLgQ27Zt\nq+KqQGZm5Vvu6Zubm6NR72dM+fn5aNnSHZmZefjkkyVo0aKlxY1Yt+TPD7Ds+lly3QDWz9yVrZ8g\nCBgzZjj69AnAxImv6n30fOn9KiPZM3k3Nze4ubkBAOzt7eHp6YmMjIxySf7w4cMYMmQIAMDb2xu3\nb99GVlYWXF1dJYm5Pvnhh+9x6NAB5OffR9u2bTFo0MtSh0REZHYUCgU+/3wVVCoPae4vyV0fkpKS\nggsXLqBz587l3s/IyICHx4P/GA8PD6jVaiZ5Ixg+fDRee+1Vi/5rm4jIGKRK8IAJDLy7e/cuZsyY\ngQ8//BD29vaPHH/4aYIhujqIiIgskaQt+aKiIsyYMQMDBw5Enz59Hjnu7u4OtVqtfa1Wq6FSqaq8\nZqNGdlAoDLOoQEWqehZiCVg/82bJ9bPkugGsnzk6dOgQbG1t4ebW3WTqJ1mS12g0+PDDD+Hp6Vnp\nVLTevXtj06ZNCAoKwu+//46GDRvq7KrPyblngGgrVp8Gj1gi1s98WXLdANbP3AiCgOXLw5GcnIwV\nK0o2ETP2IPDKSJbkz5w5gz179qBt27YYPHgwAGDmzJlIS0sDAIwcORJ+fn6Ii4tD3759YWtri/Dw\n8KouSUREBKAk8SZcLFm3o0M7LygU+kl3BQUF2BsdAwAIDvRHbm4OZsyYioCAfpg1a47JPVKWLMn7\n+Pjg4sWLOsvNmzfPCNEQEZGlEAQBu6KPw8q+KQAgOfo4Bgf61jnRFxQUYMEXm2Hr3hEAsO+dfyM1\n+TQWL15u1LnvNSH5wDsiIiJ9SriYBCv7prCSy0u+7JtqW/V1sTc6BrbuHSFXKCBXKODYpCNCxk8z\n2QQPMMkTERHViqq5F+zsHp0VZkqY5ImIyKJ0aOeF4rupKBbFkq+7qejQzqvO1w0O9Ed+xnmIggBR\nEJCfcR7Bgf56iNhwmOSJiMiiKBQKDA70hadrETxdi+r8PF4URRw/fhRKpRJzpoegrXM22jpnY870\nECiVSt0XkJBJrHhHRESkTwqFAt4d29f5OunpakyfPgUBAf3g69sDSqUSwwb110OExsEkT0REVIHY\n2BgsWbIAixYtM+nBdVVhkiciIipDFEUsWxaO5OQkREXthJOTs9Qh1RqfyRMREZWRnZ0NlcoDkZHr\nzTrBA2zJExERlePu7o7Q0ElSh6EXbMkTERFZKCZ5IiKqtzIzMyGKotRhGAyTPBER1UuxsTEYN24E\n1Oo0qUMxGD6TJyKieqXs1rDmPnpeF7bkiYio3lCr0zB69DC4urpZxOh5XdiSJyKiemP16pWYPXse\nunTpJnUoRsEkT0REJkUQBO3WsB3aedVq3fnKrvHxxwv1F6gZYHc9ERGZDEEQsCv6OK5kWeNKljV2\nRR+HIAhGv4alYJInIiKTkXAxCVb2TWEll5d82TfVtshreg0Atb6GpWCSJyIiiyKKAvZErUL07m+l\nDkVyTPJERGQyOrTzQvHdVBSLYsnX3VR0aOdV7fPV6jQsmj8H9korBAx8pVbXsCQceEdERCZDoVBg\ncKDvg0Fz3X2rPfCu7NawnTp51+oalqZ+1pqIiEyWQqGAd8f2NTrnyJFYbNiwrtziNjW9hiVikici\nIrPn69sDPXr4QSaTSR2KSWGSJyIisyeXy6UOwSRx4B0REZGFYpInIiKzkZ6uxmuvhaGwsFDqUMwC\nkzwREZmF2NgYjB8fgkmTXoWNjY3U4ZgFPpMnIiKTUlBQgL3RMQCA4EB/KBSKMlvDfmfxO8fpE5M8\nERGZjIKCAnz86Xr8jSYAgF/Of4Nr5w4iIKAfZs2aw9HzNcQkT0REJmPHnv1IK3CFtZ0DACC9QIUX\n+w7EpEkTJI7MPPGZPBERmYxjJ36BvIEDIJMBMhnkDRwQn5gsdVhmi0meiIhMhufjLZD151loRAEa\nUUDWn2fh+XgLqcMyW+yuJyIivRME4cHa8e28Klw7/uEBdidP/gyfzm0Rf/UE/k47DwBo2EDA1Inj\njBe4hZE0yX/wwQeIi4uDi4sLfvjhh0eOnzp1CtOmTUOLFiV/xQUEBGDatGnGDpOIiGpAEATsij6u\n3dM9Ofo4BgeW3ySmoKAAC77YDFv3jigWRXw9IgRNGinx+edf4umnn8XXG6IAAJPHTYaDg4Mk9bAE\nkib5oUOHYuzYsZg1a1alZZ5++mmsWbPGiFEREVFdJFxMgpV9U1iVLjVr3xQJF5PKbRizNzoGtu4d\nkX83F9FbluDxds8iKKi7dnrczGmTpAjd4kia5H18fJCSkiJlCEREJJE/k3/Diehv4f/yDLg1bQOZ\nLFvqkCyOSQ+8k8lkOHv2LAYOHIjJkyfj8uXLUodEREQ6dGjnheK7qSgWxZKvu6no0M6rXJngQH8g\nPx2DJy6CW9M2yM84X/Ie6ZVJD7xr3749YmNjYWtri7i4OLz22muIjo6WOiwiIqqCQqHA4EDfBwPv\nuvs+MvBOqVTi84Xv/zPw7j6CR4RAqVRKEK1lk2k0Go2UAaSkpGDq1KkVDrx7mL+/P3bu3Aln58qX\nNBQEEQoFtxwkIiIy6ZZ8VlYWXFxcIJPJEB8fDwBVJngAyMm5Z4zQAABubo7IzMwz2v2MjfUzb5Zc\nP0uuGyB9/aoz/a0m12j3hCd+/fU0fH17AJC+foZm7Pq5uTlWekzSJP/WW2/h9OnTyM3NhZ+fH6ZP\nnw5BEAAAI0eORHR0NLZs2QK5XA5bW1usWLFCynCJiCxedaa/1eQaf+dkYsb0AIweOUKb5Ml4JE3y\nupJ2SEgIQkJCjBQNERFVZ/pbda9x8fxp7N6yCiNC38Vzz3npPpH0zqS764mIyPyIoog9WyOhTr2O\nN+Z+CaXSHkCR1GHVSyY9hY6IiIyrOtPfdGni7oKGdtaY/OZiKJX2tboG6Qdb8kREpFWd6W+6NGnS\nFCuWLKzTNUg/+L9ORETlKBSKGj2DN9Q1qO7YXU9ERLWWmZkJURSlDoMqwSRPRES1Ehsbg3HjRkCt\nTpM6FKoEu+uJiKhGBEHA8uXhSE5ORlTUTu3OcWR62JInIqJqU6vTMHr0MLi6uiEycj0TvIljS56I\niKpt9eqVmD17Hrp06SZ1KFQNTPJERFRtH3+8UOoQqAaY5ImI6qGqNqHRxwY1ZBr4TJ6IqJ4p3UDm\nSpY1rmRZY1f0ce3mYGWPJWdYlTtG5odJnoionim7CY2VXA6rfzahKT2mUbrjh21rcOiHjeWOkflh\nkiciIq2srEysDJ8Bh4aN0G/IBKnDoTpikiciqmc6tPOCkPcX0tRqpKnVEPL+Qod2XoiNjcGyxR9h\nwKDh6NVvBDTFxdxcxsxxNAURUT2k0QCF+Xkl/25gjaNH47Bx47fYuvV72Ns7cHMZC8FPjoionkm4\nmATrhi3wWCM5AKBYFOHUqABr126ATCYDAG4uYyHYXU9ERJDL5doET5aDSZ6IqJ7p0M4LxXdTUSyK\nJV987m6xmOSJiOqR9HQ13nhjGvr3ehqerkXwdC3C4EA+d7dU/FSJiOqJ2NgYLFmyEIsWLYWdnR2f\nu9cDTPJERGauomVoCwoKsDc6BgDQr3dPrFz56T9bw37HnePqEXbXExGZsYqWqL1z5w4WfLEZl3Jd\ncCHbGX69/eHk1Ihbw9ZDbMkTEZmxskvUAgDsm+LrDVGwde8EuUIBuUKBwDEfwa0pOHq+HmJLnojI\nwtk3dJE6BJIIkzwRkRkRBAHnzifi3PlECIJQ4RK1k8eNRH7GeYiCAFEQkJ9xHsGB/lKHThJgkici\nMhOVbRFbukTtxXPHcDkpEUqlEnOmh6CtczbaOmdjzvQQKJVKqcMnCfCZPBGRmajo+fve6BhYObTC\n7z9GIu3mNTwdNgcJF5Pg3bE9hg3qL23AJDm25ImIzFhu7i18ufgNODo1xqtvL4OdvaPUIZEJYUue\niEhCFc1xr0yHdl64dOAIsgtKut6zrp7CsZg9CB44Gq07vfhga9juvkaJnUwfkzwRkURKn7Fb2TcF\nACRHH8fgwKoTdNktYpW29vjvf3fAycmJW8NShfidQEQkkYqesSdcTEKTJs9WWr78FrGtkZKWDhcX\nFy5RSxXiM3kiIiILJWmS/+CDD/DCCy9gwIABlZZZsGABAgICMHDgQCQmJhoxOiIiw6rulq+iKOL4\n8aPcIpZqTNIkP3ToUERGRlZ6PC4uDjdu3MDBgwcxf/58fPTRR8YLjojIwBQKBQYH+la55Wt6uhqj\nRg3FhQsJ1SpPVJak3x0+Pj5ISUmp9Pjhw4cxZMgQAIC3tzdu376NrKwsuLq6GitEIiKDUigUlT5P\nL9kadgEWLVqGrl2f0lme6GEm/SdgRkYGPDw8tK89PDygVquZ5InIoomiiMWLFyA5OQlRUTu5cxzV\nmkkneQDQaDTlXnMXJSIyJTWZ517d87OysqBSeWDWrA/5O4/qxKSTvLu7O9Rqtfa1Wq2GSqWq8pxG\njeygUMgNHZqWm5tlry7F+pk3S66fKdRNEARs2f0TZLYl89zTfv4Vowb1qnair/x8R7z33kyDxW0K\nTOHzMyRTqZ9JJ/nevXtj06ZNCAoKwu+//46GDRvq7KrPyblnpOhKPsTMzDyj3c/YWD/zZsn1M5W6\nnTufiHvFLrAqEAAAxcUuiD16ptrPzCs7v0+vZ02ifoZiKp+foRi7flX9QSFpkn/rrbdw+vRp5Obm\nws/PD9OnT4cglHyzjxw5En5+foiLi0Pfvn1ha2uL8PBwKcMlItK723/fQkOnxg8WxCHSI0mT/IoV\nK3SWmTdvnhEiISKquQ7tvJAcfRz4Z1namq4bn5V+E6vCZyPsnRVo7OrBdedJ70y6u56IyJSVzluv\n6brxgiBg+fJwJCcn48C+H5GSlg6giOvOk97xu4mIqA5qOm9drU7DjBlTERDQD7NmzYFMJoOLi4sB\nI6T6TOeKd+Hh4cjLy4MgCBg9ejS8vb2xa9cuY8RGRGRxVq9eidmz52HSpCmcHkcGpzPJ//zzz3B0\ndMSxY8egUqlw8OBBfPPNN8aIjYjI4nz88UJ06dJN6jConqj22vWnT59G3759oVKpYGXFzeuIiIhM\nnc5s7eLignnz5uHAgQPw9fVFUVERRFE0RmxERGaNvytJajqT/CeffILWrVvj008/hZOTE9LT0xEa\nGmqM2IiIzJIgCFi8eD5WrvxM6lConqtWS37o0KGwtrYGADRv3ly7MxwRUX0gCALOnU/EufOJ2gW7\nKjumVqdh1KihcHFxxYwZb0kUMVEJnUk+Li4OwcHBeP311wEA8fHxmDp1qsEDIyIyBYIgYFf0cVzJ\nssaVLGvsij6uTfQPHwtfsRLjx4/G7NnzMHnyVI6eJ8npTPKff/45tm/fDicnJwBA586d8eeffxo8\nMCIiU5BwMQlW9k1hJZeXfNk31S5+U/bYpYRfcexoHOZ+tFi79zuR1Kq1GI67u3u516Vd90REVKJt\nBx94tX8KDg6C7sJERqKzJe/g4IDMzEzt61OnTqFhw4YGDYqIyFR0aOeF4rupKBbFkq+7qejQzuuR\nYwCguZemPUZkCnS25N9++22EhYXh5s2bGDNmDK5fv47Vq1cbIzYiIqMTBOHBWvTtvKBQKBDc+1ns\njY4BAAQH+mvXl6/t2vVExqLzu9Hb2xvr16/H2bNnodFo0LVrV+3zeSIiS1I6kM7qn13lkqOPlyT4\nw6dg5fQEAGDzdwdw5vh+fPbZl7Cxsanx2vVExlStPzkbNmwIPz8/Q8dCRCSpsgPpAAD2TbE3OgZW\nTk/ASi5H4rkT2L1lFd6eORM2NjbSBktUDZUm+eeee67Sk2QyGU6cOGGQgIiITI0oCvhh2xqk3byG\n6bO/QNvHlFKHRFQtlSb5HTt2GDMOIiLJtW3TGj+d+B53NM5o5NwQbrb30b93TwQPCkYnn96Y/Obi\nfwbXdZY6VKJqqTTJN2/e3JhxEBEZTUWD6wRBwPc/HsU19T0UagRkZWagcYemUCqV2LxhE7JybgMQ\n0KEdB9eR+aj0O/Wdd97B8uXLMXTo0EeOyWQytvSJyCxVNLhucKAv4hMu4HRiGuTObWBvJUexcB+3\nCpVIuJgE747t0ayZxIET1UKlSX78+PEAgPfee++RY1yqkYjMVUWD6xIuJuHq9b8AuR0gkwEyGWRy\nG+Tk3gbQSNJ4ieqi0iTfsWNHAEBaWhoGDx5c7tiuXbsMGxURkZG1frw59h7+Dnn3gZYde0HIz4ND\ngzvo0K6v1KER1ZrOFe++/fbbar1HRGQOKlrBrm2b1vhx3/dITT4FH++OsMu/hlaOuZgydgifv5NZ\nq/S7Nz4+Hn/88QdycnKwefNm7ft5eXmPbLVIRCS1igbTVeThFex8vNtj3LiRCAjoh317fkDipWSd\n1yAyF5V+B2dkZOCPP/5AQUEBzp8/r33f3t4e4eHhRgmOiKg6KhtMV1GSFgRBu4LdxT9OY2n4v7Bq\n5Zfw8XkGALh6HVmUSpN8nz590KdPHxw9ehQ9evQwZkxERDVS2WC6ihJ22bL2jk6YMfcrWCu5uA1Z\nJp19UT169MDPP/+Mv/76q1w3fUhIiEEDIyIytMc82/+zg1yR1KEQGYTOJD9r1iwkJCSgffv2kJf+\nlUxEZEI6tPNCcvRx4J/u+uK7qejQ3bfOZYnMnc4k//vvv2Pv3r2wtrY2RjxERDWma8tXURRx8uTP\n8PXtwe1hqV7ROYXOw8MDGo3GGLEQEdVa6Zav3h3bl0va6elqjBo1FBcuJOgsS2RpdH53P/744wgN\nDUWfPn3Kba3IZ/JEZOpiY2OwZMkCLFq0DF27PiV1OERGpzPJ379/Hy1atEBSUpIx4iEiqpHS+fGi\nKACQQS6nf5PhAAAgAElEQVSXo90Tnvj002VITk5CVNROODk5Sx0mkSR0JvnFixcbIw4iohornR+v\nUbrjj/NJsLF3RrvWLXAm/gDc3Nwxa9aH3GuD6rVqPYy6evUqLl68iMLCQu17D69nT0RUV9Vdta5U\nwsUkwNYDiQl/QGzgCisbe2Tn5MKtaQd4unoxwVO9pzPJr1+/Htu2bUNGRgY6d+6MX3/9FU8//bRe\nkvyRI0ewaNEiFBcXY9iwYQgLCyt3/NSpU5g2bRpatGgBAAgICMC0adPqfF8iMj01WbWulCiKuHg1\nFX8XWAGQIT/nNhrZ2RspYiLTp3N0/bZt27Bt2zY0bdoUa9euxfbt22FnZ1fnG4uiiPnz5yMyMhL7\n9u3Dvn37cOXKlUfKPf3009i1axd27drFBE9kwcquRGcll8Pqn1XrqqbB3xl/wtnFHXezb6Do/j0U\nFwslc9/beRklbiJTpjPJN2jQAPb29iguLkZxcTG8vLxw/fr1Ot84Pj4eLVu2RPPmzWFtbY2goCAc\nPny4ztclovrj97NnELf3a1jdTUH7Viq0cpND1eC2zh4AovpC50+Bra0tCgsL0bZtWyxfvlxv8+bT\n09PRpEkT7WuVSoX4+PhyZWQyGc6ePYuBAwdCpVJh1qxZaNOmTZ3vTUSmpyYr0QmCgMWL5yMp6RJe\nnzkHDm5e2nOY4Ike0NmSnzdvHoqKivD+++8jNzcXv/76K5YuXVrnG1dnQEz79u0RGxuLPXv2YMyY\nMXjttdfqfF8iMk2lK9F5uhbB07Wo0mStVqchKCgIrq5uWLt2I0YPCdR5DlF9JdNItJzd77//ji++\n+AJr164FAHz11VeQyWSPDL4ry9/fHzt37oSzc+VzXgVBhELBNfaJLNU777yDkSNHwsfHR+pQiEye\nzj95Z8yYUe51aQv8888/r9ONO3bsiBs3biAlJQXu7u7Yv38/VqxYUa5MVlYWXFxcIJPJtF35VSV4\nAMjJuVenuGrCzc0RmZl5RrufsbF+5s1S6zdr1r8ttm6lWD/zZuz6ubk5VnpMZ5J/8cUXtYm9oKAA\n0dHRenkurlAoMHfuXEycOFE7hc7T0xNRUVEAgJEjRyI6OhpbtmyBXC6Hra3tI38EEBERUeVq3F1f\nWFiICRMmYNOmTYaKqU6M/dcT/xo1X6yfNKpa8ObhYzKZrMItrk21bvrC+pk3U2rJ6xx4V5GMjIxa\nB0NE9VfpgjdXsqxxJcsau6KPQxCER44lpcsw8dWp+L//Y+8dUV3U6Jm8RqPBpUuX8Pzzzxs0KCKy\nTGUXvAEA/LPgjXfH9tpjt//OxrqV89Cpa3f06tNf2oCJzFy1nsmXksvlmDhxIrp06WLImIionkqM\nP4kftq7BqEmz0LLVk5DJiqQOicis6UzyL7/8sjHiIKJ6oKoFb25lpuHoj5sxffYXsLN3rHIxHCKq\nHp1JfujQoZDJZNpV7h7+944dOwwbIRFZjNIFb7SD67o/WLymZ88X0b17TyReSgZQVO4YEdWOzp+g\nZ555BteuXcOwYcMAAN999x1atWoFPz8/gwdHRKapplvCVodcLodcLod3x/Z1vhYRldD5k/nLL79g\n27ZtsLIqGYjfq1cvjBgxAu+9957BgyMi01ObLWH1cS4R1ZzOKXS3b9/G/fv3ta8LCwtx+/ZtgwZF\nRKardlvCPjg3r9Aa3375bxQXF9foXCKqOZ1/Pr/00ksYMWIEgoKCoNFocODAAbz00kvGiI2ILMyZ\nX0/hq68jMWrSLCisrVEsilKHRGTRdCb5mTNnwtvbG6dOnYJMJsPMmTPLTasjovqlJlvClhIEAcuX\nhyMp6RJee3M2HNy8UCyKHEFPZGDVehDm7+8Pf39/Q8dCRGagqhHyFREEAWPGDEefPgGYNWsORFGs\n9rlEVDf86SKiGlMoFNUeBa9QKPD556ugUnnU+FwiqptarV1PRFQTpQmeiIyLSZ6IiMhCVdpdHxsb\nq91HviJcDIeIHhYbGwOl0hbPPcdNrIhMQaVJfu3atQBK5sX/8ccf8PLyAgAkJSWhc+fOTPJEpFU6\nej45ORkrVvyf1OEQ0T8qTfIbN24EALz11luYPXs2vL29AQDx8fFYv369caIjIslVtIRt2fdcnB3x\n1lvTERDQD7NmzamyB5CIjEvn6PqkpCRtggeAzp07IymJK1QR1QcVLUMb3PtZ7D18Clb2TXHxj9PY\ntfkzrFr5JXx8npE4WiJ6mM6Bd7a2tti1a5f29Z49e2Bra2vQoIjINFS0hO3e6Bjte/aOTpgx9ytY\nKx2kDpWIKqCzJR8eHo733nsPc+fOBQB4eXlh6dKlBg+MiPSjrjvGFRcXIzP7FgDApZFzuWOPebb/\nZ2naIr3ESkT6pfOnvU2bNti5cyfu3LkDAHBw4F/sROairru+tW3TGtsPbIate0cAwF9Xj+H9qSPw\nY9yZGi1rS0TS0NldX1xcjO3bt2P16tVwcHBASkoKfvvtN2PERkR1VJcd4wDg0uWr8O72Ahxkubh1\n7QS8u72AK9f/xOBAX3i6FsHTtYhbxRKZMJ1JPjw8HCdOnMD//vc/AICdnR0WLlxo8MCIyDTcuZ2D\n7zeuQNH9u5DLS5J56dK03h3bM8ETmTCdSf7UqVNYvny5drBd48aNUVhYaPDAiKjuOrTzQvHd1JId\n30p3fWvnVe3zs9JvYvWSNzBwxFS8GDi8xucTkbR0/gneoEEDWFk9+FuguLjYoAERkf7UdMe4UqIo\nYtmycCQnJ+HAvh+RkpYOoIi7xhGZGZ0/rV5eXti9ezeKi4uRkpKCiIgIPPXUU8aIjYj0oDa7vmVn\nZ0Ol8sCsWR9CJpPBxcXFQNERkSHp7K7/4IMPcPr0aWRmZuJf//oXRFHEu+++a4zYiEgi7u7uCA2d\nxNXriMyczpa8g4MDB9oRERGZIe5CR1TPZWZmonHjxpDL5VKHQkR6pnMXusowyROZv9jYGCxZsgCR\nkRvQrFlzqcMhIj3TuQsdEVmeslvDRkXthJOTs+6TiMjsVGsuTGxsLE6ePAmZTIbnnnuOrXgiM/Lw\n2vVZWZmYMWMqt4Ylqgd0JvlPP/0UMTExCAoKgkajwYoVK/Dbb79h5syZxoiPiOqgorXrz538EbNn\nz0OXLt0kjo6IDE3nFLoDBw5g69atmDJlCqZOnYotW7bgwIEDern5kSNH0K9fPwQEBCAiIqLCMgsW\nLEBAQAAGDhyIxMREvdyXyFIJgoBz5xNx7nwi7ty5gy8ivsXFm/dQrNFo164fNmIsEzxRPaEzyTs5\nOUGpVGpfN2jQAE5OTnW+sSiKmD9/PiIjI7Fv3z7s27cPV65cKVcmLi4ON27cwMGDBzF//nx89NFH\ndb4vkaUqbbVfybLGhVQRY2YsxZ95TsgusMWR039AEASpQyQiI9PZXd+1a1dMnjwZQ4YMgUajwZ49\ne9CtWzfExcUBqP0o+/j4eLRs2RLNm5eM6A0KCsLhw4fh6empLXP48GEMGTIEAODt7Y3bt28jKysL\nrq6utbonkaWoaI/4hItJgK0HMrNvISH+VzRs8QxsZAJyslNg69wcF5OvoF0zO24LS1SP6EzyFy5c\nAABs3bpV+15iYqK267y2ST49PR1NmjTRvlapVIiPjy9XJiMjAx4eHtrXHh4eUKvVTPJUr1W2R7wo\nirh4NRXyBs64na/B1YPfwtHBHr79xiEz7U/YK3IxOHA8154nqkd0/rQbaipddUf0ajSaWp1HZKnK\n7hEPANDuEa9B4d1cCAWF+OPYdtjYN0KnwBBoNBrYW/2NqRPGMMET1TPV+on/888/8eeff0IURe17\ndZ1Gp1KpkJaWpn2tVquhUqnKlXF3d4dara6yzMMaNbKDQmG8lbvc3ByNdi8psH6mp5GzPezzZdok\nXyyKaORsAwBwsLmPreuWIHhEGLo+7YuMq2fweAs5hr4+pdzYGktgjp9dTbB+5s1U6qczyS9duhS7\ndu1Cq1atym05W9ck37FjR9y4cQMpKSlwd3fH/v37sWLFinJlevfujU2bNiEoKAi///47GjZsqLOr\nPifnXp3iqgk3N0dkZuYZ7X7GxvqZpqYezXD63IPu+uK7qWja1RdHj8bh8A8bMfPfX8HO3hFKZGPC\nmFFQKBTIyytCXl6RxJHrj7l+dtXF+pk3Y9evqj8odCb5Q4cO4fDhw7C1tdVrUAqFAnPnzsXEiRNR\nXFyMYcOGwdPTE1FRUQCAkSNHws/PD3Fxcejbty9sbW0RHh6u1xiIzMXDA+2Cez+LvdExAIDgQH8o\nFAr07PkiunfvicRLyQCK8GKPXsjJyZcwaiKSms4k7+HhYbDneH5+fo/0CIwcObLc63nz5hnk3kTm\n4uGBdhf3H4FMBiicngAA7D18CoMDfaFQKCCXy7V7x/P5OxHp/C3w3nvvYcqUKejevTtsbGy074eE\nhBg0MCIq8fBAO3VuEWxsHdHEufzAu9LkTkRUSmeSj4yMRFZWFi5cuMCtKIkMqKK576WKi4uRmX0L\nAHA79xaObFuDV99aDIW1tSSxEpF5qNY8+R9//LHcoDsi0q/K5r4rFAq0bdMa2w9shq17R9xIOoOf\n967G2NBpsLKyQrEoovhuKhe4IaIK6Uzyjz/+OO7duwcHBwdjxENUL1U29927Y3tcunwVHb2fwbb1\nnyI74ybenb8WnR5TQi4vGS3fobsvn78TUYV0/mawt7fH0KFD0aNHD1j/0zUok8nw3nvvGTw4IgJE\nUcBXy99Dp6d6YOyrH0JTXAy5vIjP4IlIJ51JvnXr1mjdujWAkuSu0Wi46hyRnnVo54Xk6ONAmbnv\npV3wnTu0x5hXXkWjZh2hKS5m9zwRVZvOJD99+nRjxEFk1qoaNFcdCoWiwrnvpcdeGTHgwfXZPU9E\n1VSt3xRHjx7FxYsXcf/+fe17r7/+usGCIjInVQ2aq8k19h4+BasK5r4DJYme3fNEVFM6h8wvW7YM\nkZGRWLduHTIyMrBlyxZcv37dCKERmYeyg+as5HJYaTeMqfk1Lp4/jStJ8bW6BhHRw3Qm+bi4OERG\nRsLV1RX/+c9/sHPnTuTm5hojNqJ6QxQF7IlahSOHvkOzlp5Sh0NEFkJnkrexsYG1tTVkMhkKCwuh\nUqmQnp5ujNiIzEKHdl4ovptaMme9dN56O69qn69WpyF8wVzY28ox+c3FUCrta3wNIqKK6Hxo6ODg\ngHv37qFLly54//334ebmZnFbVhLVhUKhwOBA31oNjDtyJBbh4f/BokXL0KmTNwfXEZFe6fwt8skn\nn0ChUGDWrFlYt24d7ty5g88//9wYsRGZjdoOjHNyckJU1E44OTkDAAfXEZFe6Uzybm5uAEq67SdP\nnozc3Fy4u7sbPDCi+sDbu6vUIRCRBdP5TP7NN99EXl4eCgoKMGDAAAQFBSEyMtIYsREREVEd6Ezy\n165dg6OjI2JjY/Hss8/iyJEj2L17tzFiI7IYoiji+PGjUodBRPWMziQvCAIA4PTp0+jZsydsbW25\nIx1RDaSnqzFq1FBcuJAgdShEVM/ozNaenp6YOHEifvrpJ7zwwgvIz883RlxEFiE2Ngbjx4/GBx/M\nxaRJU6QOh4jqGZ0D75YsWYJjx46hXbt2sLOzQ3p6Ot5++21jxEZktkRRxLJl4UhOTio3ep6IyJh0\ntuRtbW3h6emJS5cuASjZerZTp04GD4zIlAmCgHPnE3HufCIEQXjkdXZ2NlQqD0RGrmeCJyLJ6GzJ\n79y5ExERESgqKkKfPn2Qnp6O+fPn49tvvzVCeESm5+ENaS7uPwKZDFA4tgDwYIOa0NBJUoZJRKS7\nJb9+/Xrs2LEDjo6OAEqe0WdlZRk8MCJTlXAxCcVKd1y8fA0XL1/DzewCZBco67RBDRGRIehM8tbW\n1nBwcCh/EkfXUz0lCAIuXLqE/x09g7TbCqTlKXDqTDyKigqlDo2I6BE6s3WjRo1w9epV7evdu3ej\nSZMmBg2KyBRU9Nx954EjiD1zDdk5fyP/voCbl8/iTMxGXP7jWK03qCEiMhSdz+Q/+OADvPPOO7h+\n/Tp69eoFpVKJNWvWGCM2Isk8/Nw9Ofo4HvNwQlJ6MW7l5sOhiRfiYyJRcDsdfceF4zH7NHi6FgHg\n5jJEZDp0/iZq3bo1tm3bhuvXr0Oj0aB169b4+++/jREbkWQSLibByr4prOTykjfsm+LYqTjI7DvB\nycUFsVs/RIv2vdC1dyju30pCz4Ae3FyGiExOld31ubm5iI+Px71799CmTRu0aNECa9aswUsvvWSs\n+IhMRlMPFe7n/oU/L5xCZ9/BaOziDsXdJPR5vj26du4sdXhERI+otCW/d+9ezJkzB/b29sjPz8ei\nRYuwYsUKPPnkk9i+fbsxYyTSO0EQcObseeTk3kWHdl6PdK93aOeFSweOILtACQBwURZgUP++wMGf\n4dJoJIpFEZqCbLz4Qhd07vAku+eJyCRV+pvpq6++wvbt2/HEE0/g119/xbhx47BixQr069fPmPER\n6V3p83ZH91a4e9daO6/94USt0QCF+Xkl/25gDYVCgaH9e2qnx3VoF8DkTkQmrdLfUHK5HE888QQA\nwMfHBy1btmSCJ4tQ9nm7lVwO/DOvvewz9YSLSbBu2AItGgJWcjmKRVFbhs/eichcVJrk79+/j8uX\nLwMANBoNZDKZ9jUAtGnTxvDREUlEFAXsifoaDWzt8NLLE6UOh4ioVqpM8mFhYeXeK/s6JibGcFER\nGVCHdl5Ijj6OYvtWD+a1d/fVHler07Bo/hyomj8B/4GvVFiGiMgcVJrkmcTJUikUCgwO9EWq+iZy\ncovKzWuPjY3BkiULsGjRMnTq5P3g+TvnvhORGZLkt1Zubi5mzpyJ1NRUNGvWDJ999hkaNmz4SDl/\nf3/Y29tDLpdDoVBgx44dEkRLlkihUOCprh2RmZmnfe/IkVhs2LCu3NawfP5OROZMkiQfERGBF154\nAZMnT0ZERAQiIiLwzjvvVFh248aNcHbmVp31lSAIZUazPzrVrS7XfXgKna9vD/To4QeZTKaXexAR\nSU2SnWZiYmIwZMgQAMCQIUPwv//9r9KyGo3GWGGRiSmd6nYlyxpXsqyxK/o4BEHQ23UvpMnKXVcu\nlzPBE5FFkSTJZ2dnw9XVFQDg6uqK7OzsCsvJZDKEhobi5ZdfxrZt24wZIpmAh6e66WsLV0Ndl4jI\n1Bisuz40NLTCfefffPPNcq9lMlmlractW7bA3d0dt27dQmhoKFq3bg0fH58q79uokR0UCnntA68h\nNzdHo91LClLWr5GzPezzZdr144tFEY2cbeock1h0DxvXfIqwmQtgb99Ab9c1RZZYp1KWXDeA9TN3\nplI/gyX5devWVXrMxcUFmZmZcHNzQ0ZGBho3blxhOXd3dwBA48aN0bdvX8THx+tM8jk592ofdA25\nuTmWG7hlaaSuX1OPZjh97sFOcMV3U9G0q2+dYiodPd+7/yhYWcmRd/ueXq5riqT+/AzJkusGsH7m\nztj1q+oPCkkG3vn7++P7779HWFgYdu3ahT59+jxSJj8/H6IowsHBAffu3cOxY8fw+uuvSxAtSaV0\nqps+prEJgoDly8ORnJyMqKidsLd3qHAKHRGRJZHkmXxYWBh+/vlnBAYG4uTJk9pFdtLT07X/zsrK\nQkhICAYNGoThw4ejV69e6N69uxThkoQUCoV2Kdm6JPgxY4bD1dUNkZHr4eTkrJ1CV5frEhGZOpnG\nwoavG7uLhF1O5iE9XQ2VyqPce5ZUv4pYcv0suW4A62fuTKm7XpKWPJGxPZzgiYjqAyZ5IiIiC8Uk\nTxYlNjYGJ0+ekDoMIiKTwCRPFkEQBCxePB8bN36LJ598UupwiIhMApM8mT21Og2jRw8rN3qeiIgk\nmidPpC9HjsQiPPw/WLRoGbp2fUrqcIiITAqTPJk1JyenclvDEhHRA0zyZNa8vbtKHQIRkclikidJ\n6dov3lD7yRMR1QcceEeS0bVffNnjyRlWWPr5Gr3sJ09EVF8wyZNkdO3rXnr89u1bWBn+BtIycrjv\nOxFRDbDvk0xaYvxJ/LB1DUZNmoWWrZ4EUCR1SEREZoMteZJMh3ZeKL6bimJRLPm6m4oO7bwAAKIo\nYt+eHTj6438xffYXaNnqyXLHiYhIN7bkSTJV7RefnZ2NJk2aYu/uPUi8lAyA+74TEdUUf2OS3ulj\nRLy7uztCQycBALw7ttdrfERE9QW760mvdI2Yr21ZIiKqOSZ50itdI+YrKnvnzt8AUGVZIiKqOSZ5\nklRi/El8Gf4GcnMypQ6FiMjiMMmTXlU1Yr4sQRCwb8927eh550ZuHD1PRKRnTPKkV6Uj5j1di+Dp\nWoTBgY+OiC/dGtbdXYW9u/eg02PKSssSEVHt8Tcq6Z1CoahyRPzq1Ssxe/Y8dOnSDQBHzxMRGQqT\nPBndxx8vlDoEIqJ6gUme9I47xxERmQY+kye9enju+84DRzj3nYhIImxikV6Vzn3XQIO9276CtbUN\n2rby4HN3IiIJsCVPepd7KxP/t/B1ODRshMDBoVKHQ0RUb7ElT3qVlX4Ta5bOxshJH+LxNh3+mfvu\nK3VYRET1EpM86c2RI7HYvHkDDuz7ESlp6eDOcURE0uJvX9IbX98e6NHDDzKZDC4uLlKHQ0RU7zHJ\nk97I5XKpQyAiojI48I6IiMhCMclTtRQUFGDH7v3YsXs/bty4gddeC0NhYaHUYRERURWY5EmngoIC\nLPhiMy7luuDg6esIGhiMceNCYWNjI3VoRERUBUmS/IEDBxAUFIQnn3wSCQkJlZY7cuQI+vXrh4CA\nAERERBgxQiprb3QMGrg8iZMHNyDh9AG8PPUz/KXOkTosIiLSQZIk7+XlhZUrV8LHx6fSMqIoYv78\n+YiMjMS+ffuwb98+XLlyxYhR1m8FBQXYvHUPduzej/sFBdizbi7sHJwR/Mq/0cDWQerwiIioGiQZ\nXe/p6amzTHx8PFq2bInmzZsDAIKCgnD48OFqnUt1U9o979TcG4WFdshL/Q2+fi/B7YkeKBZF5Gec\nR/CIEKnDJCIiHUx2Cl16ejqaNGmifa1SqRAfHy9hRPXH3ugY2Lp3hFxuDblCBsem3dDZLg02NtkA\ngOARIVAqlRJHSUREuhgsyYeGhiIrK+uR92fOnAl/f3+d58tkslrdt1EjOygUxpuv7ebmaLR7GUtD\nR1vY3Cv5P7SxVkC00sDVxQkhIwZKHJn+WeLnV5Yl18+S6wawfubOVOpnsCS/bt26Op2vUqmQlpam\nfa1Wq6FSqXSel5Nzr073rQk3N0dkZuYZ7X7GEBsbA6XCCn+nnPunu76ke77nkBCLq6slfn5lWXL9\nLLluAOtn7oxdv6r+oJB8Cp1Go6nw/Y4dO+LGjRtISUlBYWEh9u/fj969exs5uvpDEAQsXjwfGzd+\nC2/vLpgzPQTeqjy0dc7GnOnsniciMkeSJPlDhw7Bz88P586dw6uvvopJkyYBKHkOHxYWBgBQKBSY\nO3cuJk6ciKCgIPTv35+D7vSk7MI2BQUFUKvTMHr0MLi6uiEycj2cnJyhVCoRMmIghg3qzwRPRGSm\nZJrKmtJmythdJObW5VQ6ct7WvSMA4PIvO5GafBqLFy9H165PlStrjvWrCdbPfFly3QDWz9yZUne9\nyY6uJ8PQjpz/Z/tXxyYdEeLr80iCJyIi8yf5M3mSlqq5F+zs7KUOg4iIDIBJvp4JDvRHfsZ5iIIA\nURBKFrYJ1D2lkYiIzA+TfD0hiiKOHz8KpVKJOdND0NY5myPniYgsHJN8PZCersaoUUNx4ULJZkBK\npRLDBvXnyHkiIgvHgXcWLjY2BkuWLMCiRcs4uI6IqJ5hkrdQoihi2bJwJCcnISpqJ5ycnKUOiYiI\njIzd9RYqOzsbKpWHdnEbIiKqf9iSt1Du7u4IDZ0kdRhERCQhtuSJiIgsFJO8BcjMzIQoilKHQURE\nJoZJ3sw8vLlMbGwMxo0bAbU6TffJRERUr/CZvBkpu7lMsSji6xEhaNJIydHzRERUISZ5M1K6uUz+\n3VxEb1mCx9s9i6Cg7kzwRERUISZ5M3Qmdjt8+0+CW1NPyGTZUodDREQmis/kzUjp5jLdgybDrakn\nN5chIqIqsSVvRko3l9kbHQMACB7BzWWIiKhyTPImThRFyOVy7evSzWWIiIh0YXe9iRIEAYsXz8fK\nlZ9JHQoREZkptuRNREFBgbYb3se7Pd599w0EBPTDpElTJI6MiIjMFZO8CSg7//1G0hl8NG8W1kZE\n4Nlnn5c6NCIiMmPsrjcBpfPfb149h4RT+/Hy1M/wlzpH6rCIiMjMsSVvQpq36YIWT3RDsSgCuC91\nOEREZObYkjcBpfPfNcUaFIsi578TEZFesCVvAjj/nYiIDIEteSN4eOe49HQ1XnstDIWFhdoypfPf\nhw3qzwRPRER6wZa8gZUdOQ8Ae9+eB/WVXxAevhw2NjYSR0dERJaMSd7ASkfOy2QynIhej+z065gy\ncRq6dn1K6tCIiMjCsbveCIpFEbsiZ8POwRn9x8yFnZ291CEREVE9wCSvZw8/fw8O9Mf97Avo86+3\n0PmFgSjITODIeSIiMgomeT0qff5+KdcFl3JdsOCLzQCAOdND0K0l0NY5G3Omc+Q8EREZB5/J61Hp\n83e5ouS/1da9I/ZGx2hHzRMRERmTJEn+wIEDWLlyJa5evYodO3agQ4cOFZbz9/eHvb095HI5FAoF\nduzYYeRIa+5G0hk0UNqhWetOUodCRET1nCRJ3svLCytXrsS8efN0lt24cSOcnZ2NEFXNFBQUYPPW\nn3A7Lx/Bgf5QKBS4+MdpnIs7jMAxH0EUhJKV60aESB0qERHVU5IkeU9Pz2qX1Wg0BoykdkqfvTs1\n90ZhoR2Oh6/CXwmx6NevP2IPHcS+gz8BuM+V64iISFIm/UxeJpMhNDQUVlZWGDlyJIYPHy51SADK\nPHuXW+Pm1d9wbF8Uxo0Zq937nc/fiYjIFBgsyYeGhiIrK+uR92fOnAl//+pNIduyZQvc3d1x69Yt\nhM6L5KkAAA47SURBVIaGonXr1vDx8dF3qHXSwNYBgyeF4/Em3DWOiIhMi0wjYX/42LFj8f7771c6\n8K6slStXws7ODhMmTKiynCCIUCjk+gqxQgUFBXhvYSSUbiVxF2QmYOmHk9g1T0REJkXy7vrK/sbI\nz8+HKIpwcHDAvXv3cOzYMbz++us6r5eTc0/fIVbo3bAROPLziZKBd2EjkJdXhLy8IqPc21jc3ByR\nmZkndRgGw/qZL0uuG8D6mTtj18/NzbHSY5IshnPo0CH4+fnh3LlzePXVVzFp0iQAQHp6OsLCwgAA\nWVlZCAkJwaBBgzB8+HD06tUL3bt3lyJcAIAoijh+/Kj2tVKpRMiIgdw1joiITJYkLfm+ffuib9++\nj7yvUqkQEREBAGjRogV2795t7NAqlJ6uxvTpUxAQ0A++vj2kDoeIiKhaJO+uN3WxsTFYsmQBFi1a\nxp3jiIjIrDDJV0IURSxbFo7k5CRERe2Ek5PpLchDRERUFW5QU4ns7GyoVB6IjFzPBE9ERGaJLflK\nuLu7IzR0ktRhEBER1Rpb8kRERBaqXrbkCwoKsDc6BgAQHOiPvLw8NG7cGHK5YRfRISIiMqZ615Iv\n3VzmUq4LLuW6YMrb8zBmzHCo1WlSh0ZERKRX9a4lX7q5jEwmw4no9chOv44pE6ehWbPmUodGRESk\nV/WuJQ8Ad/7Owvdfvw87B2f0HzMXdnb2UodERESkd/WuJR8c6I81Lw/H84HjoWrRFvkZ5xE8MkTq\nsIiIiPSu3iV5pVKJvTu3/TPwLhvBI0K49jwREVmkepfkgZJEP2xQf6nDICIiMiiLfyYviqLUIRAR\nEUnCYpO8IAhYvHg+Vq78TOpQiIiIJGFxSX7H7v24fv06Ro8eBhcXV8yY8ZbUIREREUnC4p7JHzx1\nDR/Nm4W1ERF49tnnpQ6HiIhIMhbXkk84fQAvT/0Mf6lzpA6FiIhIUjKNRqOROgh9+uDLYxDFInir\n8hAyYqDU4RAREUnG4pI8ERERlbC47noiIiIqwSRPRERkoZjkiYiILBSTPBERkYVikiciIrJQTPI1\ncODAAQQFBeHJJ59EQkJCpeX8/f0xYMAADB48GMOGDTNihHVT3fodOXIE/fr1Q0BAACIiIowYYd3k\n5uYiNDQUgYGBmDBhAm7fvl1hOXP6/KrzWSxYsAABAQEYOHAgEhMTjRxh3eiq36lTp/DUU09h8ODB\nGDx4MFatWiVBlLXzwQcf4IUXXsCAAQMqLWPOn52u+pnzZwcAaWlpGDt2LIKCghAcHIwNGzZUWE7y\nz1BD1Xb58mXN1atXNWPGjNGcP3++0nK9evXS5OTkGDEy/ahO/QRB0PTp00fz119/aQoLCzUDBw7U\nXL582ciR1s6SJUs0ERERGo1Go/nqq680y5Ytq7CcuXx+1fksYmNjNZMmTdJoNBrN77//rvnXv/4l\nRai1Up36nTx5UvPqq69KFGHd/PLLL5qEhARNcHBwhcfN+bPTaHTXz5w/O41Go8nIyNAkJiZqNBqN\n5s6dO5qAgACT/PljS74GPD090apVq2qV1Zjh8gPVqV98fDxatmyJ5s2bw9raGkH/3969xkRxdgEc\n/28XqMhFRWAthbZqFLyhSZXENBSqGBWCqYjRRm0larDRUrUKGKQBQ6F3RWxCmxr1g9V6RQmSpsWI\nliJEI5oYLxUUocVFQC4rCGzZ9wNxAsKy24Kwu+/5feKZmTxzjgdynJndecLCyMvLG6QI++fcuXMs\nXrwYgMWLF/Pbb78ZPdYa6mdOLfLy8pScp0+fTmNjIzU1NUMR7r9mzb9r5pg5cyaurq5G91tz7cB0\nftbOw8ODSZMmAeDk5MT48eOprq7udowl1FCa/AugUqmIiooiIiKCo0ePDnU4A0qr1fLKK68oY41G\ng1arHcKIzFdbW4u7uzsA7u7u1NbW9nqctdTPnFpUV1czZswYZTxmzBgePnw4aDH2hzn5qVQqrl69\nyqJFi1i3bh13794d7DBfGGuunTlsqXaVlZXcvHkTf3//btstoYY2t0BNf0VFRfX6P63NmzczZ84c\ns+Y4fPgwnp6e1NXVERUVxbhx45g5c+ZAh/qf9Dc/lUr1IsIaMMby27RpU7exSqUymosl168rc2vx\n/F0JS6/hM+bEOXnyZM6fP4+joyP5+fls2LCBX375ZRCiGxzWWjtz2Ertnjx5QkxMDAkJCTg5OfXY\nP9Q1lCb/nP379/d7Dk9PTwDc3NyYN28e169ft5gm0d/8NBoNVVVVyvjhw4doNJr+hjVg+spv9OjR\nPHr0CA8PD6qrq3Fzc+v1OEuuX1fm1MLT07PblYOl1asv5uTn7Oys/BwUFERycjL19fWMHDly0OJ8\nUay5duawhdq1t7cTExPDokWLCAkJ6bHfEmoot+v/I2PPbFtaWtDpdAA0Nzfz+++/M3HixMEMbUAY\ny2/q1KmUl5dTWVlJW1sbZ8+eZe7cuYMc3X8zZ84cTp06BUBWVlavf5TWVD9zajF37lyysrIAKCkp\nwdXVVXlkYenMya+mpkb5Xb1+/TqAVTWJvlhz7cxh7bUzGAwkJCQwfvx4Vq9e3esxllBDWaDmX/j1\n119JSUnh8ePHuLi4MGnSJH788Ue0Wi2JiYn88MMPVFRUsHHjRgD++ecfwsPDiY6OHuLIzWNOfgD5\n+fmkpqbS0dFBZGSk1eRXX1/Ppk2bqKqq4tVXX2X37t24urpadf16q8WRI0cAWL58OQA7d+7k4sWL\nODo6kpaWxpQpU4Yy5H/FVH6HDh3i8OHDqNVqHB0diY+PZ8aMGUMctXm2bNlCcXEx9fX1jB49mo8+\n+gi9Xg/YRu1M5WfNtQO4fPkyK1euxNfXV7kFv3nzZuXuk6XUUJq8EEIIYaPkdr0QQghho6TJCyGE\nEDZKmrwQQghho6TJCyGEEDZKmrwQQghho6TJCyGEEDZKmrwQFqKtrY3PP/+cefPmsXDhQpOL6ADs\n2LGDK1eumJx7z549nD17tl/xrVq1ivPnz/drjoFQXFxMQUGBMtZqtbz//vvK2M/Pj5aWlqEITQiL\nI6+1FcJCJCUl8fTpU3JycnBwcODPP/9k7dq1jBw5stfX6nZ0dJCSkmLW3DExMQMSoyW8O72oqIjm\n5mbeeustoPP1t8bW8hbi/500eSEswF9//UVubi75+fk4ODgAMGHCBNavX8/evXs5cOAAJ0+e5MyZ\nMzg7O1NeXs5XX33FZ599xpo1awgODkar1RIbG0ttbS0+Pj4YDAYCAwNZsWIF8fHxTJs2jRUrVpCR\nkcG9e/fQ6XRUVFTw2muvkZ6ezrBhwygsLCQ9PZ3W1lb0ej0ffvghoaGhJuM/dOgQBw8exNnZmbff\nfpsjR45w6dIlioqK+PLLLzlx4gRAt/GjR4/45JNP0Ol0tLW1ERQUxLZt2wCMxlheXs7PP/9MR0cH\nhYWFhIWFsXDhQpYsWUJRUVGPuMrKykhLS+Px48e0t7fzwQcfEBERQUtLC3FxcZSWlmJnZ8fYsWPZ\nvXv3AFZUCMsgTV4IC3Dnzh1ef/31HutvT58+nfT0dGV87do1zpw5g4+Pj7Lt2dV1SkoKs2fPZv36\n9fz999+Eh4cTGBjY7Zhnbty4wYkTJ3B2dmbNmjVkZ2ezdOlSpkyZwk8//cRLL71ETU0NS5YsITAw\nEBcXF6Ox37p1i8zMTE6fPo2bmxvJyclmXfGPGDGCzMxMhg8fTnt7O2vXruXixYtKzMZiXL58Oc3N\nzcTGxgKdy3z2dj69Xs/WrVv5+uuvGTduHDqdjsjISGbMmEFpaSlPnjwhJycHgKamJpPxCmGNpMkL\nYQHMfbv0m2++2a3Bd1VcXExiYiIAXl5ezJ492+g8gYGByipg/v7+PHjwAIDa2lq2b9/OgwcPUKvV\nNDQ0cO/evR7rZD9/3nfeeUdZ1W/ZsmXk5uaazEWv1/PFF19QUlKCwWCgpqaGW7duKU3eWIwGg8Gs\nf6/79+9TVlbGli1blG3t7e2UlZXh5+dHWVkZO3fuJCAggODgYJPzCWGNpMkLYQEmTpxIeXk5DQ0N\njBgxQtleUlKCn5+fMh4+fHif83RtfsYaoUqlwt7eXhmr1WpaW1uBzs8FhISE8N133wEwf/58ZZ8x\nKpXK6HnVanW3cde59u/fT1NTE8eOHcPBwYFPP/1U2d9bjE+fPu0zjucZDAZGjRqlrAL2vJycHP74\n4w8uXLjArl27yM7OVh6VCGEr5NP1QlgAb29vFixYQFJSEm1tbUDnLfzvv/9eWRXPlICAAKWhVVVV\n9fqMGno2/65Xxk1NTXh5eQFQUFCgXD2bOm9+fj51dXUAHD9+XNnn4+NDRUUFjY2NGAwG5fY4gE6n\nw8PDAwcHB7RaLXl5eX3G+IyLi4uyHHBfxo4dy7Bhwzh9+rSyrbS0FJ1Oh1arRaVSERISwvbt26mr\nq6OhocHknEJYG7mSF8JCJCUl8e233xIaGoq9vT0vv/wyO3bsUD5Zr1Kp+nzWnZCQQGxsLNnZ2Xh7\ne+Pv79/rs/Tn5+k63rp1K8nJyWRkZDBt2rRudxGM8fX1JTo6mvfeew8nJyeCgoKUfRqNhqioKCIi\nInB3d2fWrFmUlpYCnV/J+/jjjwkPD0ej0XR7vNBXjCEhIWRlZfHuu+8SFhZGaGhoj2MB7OzsyMzM\nJDU1lX379tHR0YG7uzu7du3i9u3bfPPNN0DntxSio6Px8PAwmasQ1kaWmhXCRrS2tmJnZ4daraa6\nupqlS5dy8OBB3njjjUGNo7KyksjISC5dujSo5xVC9CRX8kLYiPv37xMXF4fBYECv17Nx48ZBb/DP\nWML36YUQciUvhBBC2Cz54J0QQghho6TJCyGEEDZKmrwQQghho6TJCyGEEDZKmrwQQghho6TJCyGE\nEDbqf7xf1sar2G8OAAAAAElFTkSuQmCC\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f24fc02f250>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(8, 6))\n",
"\n",
"blue = sns.color_palette()[0]\n",
"ax.plot((w_min, w_max), (w_min, w_max), '--', c='k', lw=0.75,\n",
" label='Perfect agreement');\n",
"ax.scatter(qs.w, boot_qs.w, c=blue, alpha=0.5);\n",
"\n",
"\n",
"ax.set_xlim(w_min, w_max);\n",
"ax.set_xlabel('Original quantiles');\n",
"\n",
"ax.set_ylim(w_min, w_max);\n",
"ax.set_ylabel('Resampled quantiles');\n",
"\n",
"ax.set_title('Q-Q plot for $w$');\n",
"ax.legend(loc=2);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that both of the resampled distributions agree quite closely with the original distributions. We have only produced Q-Q plots for $u$ and $w$ because $v$ is binary-valued.\n",
"\n",
"While at first non-summarized boostrap resampling may appear to counteract the benefits of summarizing the original data frame, it can be quite useful when training and evaluating [online learning](https://en.wikipedia.org/wiki/Online_machine_learning) algorithms, where iterating through the locations of the bootstrapped data in the original summarized data frame is efficient."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summarized bootstrap\n",
"\n",
"To produce a summarized data frame, the counts of the resampled data frame are sampled from a [multinomial distribution](https://en.wikipedia.org/wiki/Multinomial_distribution) with event probabilities given by `weights`."
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"boot_counts = pd.Series(np.random.multinomial(n_boot, weights), name='count')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, we compare the distribution of our bootstrapped data frame to that of the original with Q-Q plots. Here our summarized quantile function is quite useful."
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"boot_count_qs = quantile(summ_df, boot_counts, q=ps)"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\nhPAB/wAdN3aYTodIsAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f24fbf04110>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(8, 6))\n",
"\n",
"ax.plot((u_min, u_max), (u_min, u_max), '--', c='k', lw=0.75,\n",
" label='Perfect agreement');\n",
"ax.scatter(qs.u, boot_count_qs.u, c=blue, alpha=0.5);\n",
"\n",
"ax.set_xlim(u_min, u_max);\n",
"ax.set_xlabel('Original quantiles');\n",
"\n",
"ax.set_ylim(u_min, u_max);\n",
"ax.set_ylabel('Resampled quantiles');\n",
"\n",
"ax.set_title('Q-Q plot for $u$');\n",
"ax.legend(loc=2);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f24fbdd3410>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(figsize=(8, 6))\n",
"\n",
"ax.plot((w_min, w_max), (w_min, w_max), '--', c='k', lw=0.75,\n",
" label='Perfect agreement');\n",
"ax.scatter(qs.w, boot_count_qs.w, c=blue, alpha=0.5);\n",
"\n",
"ax.set_xlim(w_min, w_max);\n",
"ax.set_xlabel('Original quantiles');\n",
"\n",
"ax.set_ylim(w_min, w_max);\n",
"ax.set_ylabel('Resampled quantiles');\n",
"\n",
"ax.set_title('Q-Q plot for $w$');\n",
"ax.legend(loc=2);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, we see that both of the resampled distributions agree quite closely with the original distributions."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# Linear Regression\n",
"\n",
"Linear regression is among the most frequently used types of statistical inference, and it plays nicely with summarized data. Typically, we have a response variable $y$ that we wish to model as a linear combination of $u$, $v$, and $w$ as\n",
"\n",
"$$\n",
"\\begin{align*}\n",
" y_i = \\beta_0 + \\beta_1 u_i + \\beta_2 v_i + \\beta_3 w_i + \\varepsilon,\n",
"\\end{align*}\n",
"$$\n",
"\n",
"where $\\varepsilon \\sim N(0, \\sigma^2)$ is noise. We generate such a data set below (with $\\sigma = 0.1$)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"beta = np.array([-3., 0.1, -4., 2.])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"noise_std = 0.1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"X = dmatrix('u + v + w', data=df)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"y = pd.Series(np.dot(X, beta), name='y') + sp.stats.norm.rvs(scale=noise_std, size=N)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0 7.862559\n",
"1 3.830585\n",
"2 -0.388246\n",
"3 1.047091\n",
"4 0.992082\n",
"Name: y, dtype: float64"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each element of the series `y` corresponds to one row in the uncompressed data frame `df`. The [`OLS`](http://statsmodels.sourceforge.net/devel/generated/statsmodels.regression.linear_model.OLS.html) class from [`statsmodels`](http://statsmodels.sourceforge.net/devel/index.html) comes quite close to recovering the true regression coefficients."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"full_ols = sm.OLS(y, X).fit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"const -2.999658\n",
"x1 0.099986\n",
"x2 -3.998997\n",
"x3 2.000317\n",
"dtype: float64"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"full_ols.params"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To show how we can perform linear regression on the summarized data frame, we recall the the [ordinary least squares estimator](https://en.wikipedia.org/wiki/Ordinary_least_squares) minimizes the [residual sum of squares](https://en.wikipedia.org/wiki/Ordinary_least_squares#Estimation). The residual sum of squares is given by\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"RSS\n",
" & = \\sum_{i = 1}^n \\left(y_i - \\mathbf{x}_i \\mathbf{\\beta}^{\\intercal}\\right)^2.\n",
"\\end{align*}\n",
"$$\n",
"\n",
"Here $\\mathbf{x}_i = [1\\ u_i\\ v_i\\ w_i]$ is the $i$-th row of the original data frame (with a constant added for the intercept) and $\\mathbf{\\beta} = [\\beta_0\\ \\beta_1\\ \\beta_2\\ \\beta_3]$ is the row vector of regression coefficients. It would be tempting to rewrite $RSS$ by grouping the terms based on the row their features map to in the compressed data frame, but this approach would lead to incorrect results. Due to the stochastic noise term $\\varepsilon_i$, identical values of $u$, $v$, and $w$ can (and will [almost certainly](https://en.wikipedia.org/wiki/Almost_surely)) map to different values of $y$. We can see this phenomenon by calculating the range of $y$ grouped on $u$, $v$, and $w$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"reg_df = pd.concat((y, df), axis=1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"count 9997.000000\n",
"mean 0.297891\n",
"std 0.091815\n",
"min 0.000000\n",
"25% 0.237491\n",
"50% 0.296838\n",
"75% 0.358015\n",
"max 0.703418\n",
"Name: y, dtype: float64"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"reg_df.groupby(('u', 'v', 'w')).y.apply(np.ptp).describe()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If $y$ were uniquely determined by $u$, $v$, and $w$, we would expect the mean and quartiles of these ranges to be zero, which they are not. Fortunately, we can account for is difficulty with a bit of care.\n",
"\n",
"Let $S_j = \\{i\\ |\\ \\mathbf{x}_i = \\mathbf{z}_j\\}$, the set of row indices in the original data frame that correspond to the $j$-th row in the summary data frame. Define $\\bar{y}_{(j)} = \\frac{1}{n_j} \\sum_{i \\in S_j} y_i$, which is the mean of the response variables that correspond to $\\mathbf{z}_j$. Intuitively, since $\\varepsilon_i$ has mean zero, $\\bar{y}_{(j)}$ is our best unbiased estimate of $\\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}$. We will now show that regressing $\\sqrt{n_j} \\bar{y}_{(j)}$ on $\\sqrt{n_j} \\mathbf{z}_j$ gives the same results as the full regression. We use the standard trick of adding and subtracting the mean and get\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"RSS\n",
" & = \\sum_{j = 1}^m \\sum_{i \\in S_j} \\left(y_i - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)^2 \\\\\n",
" & = \\sum_{j = 1}^m \\sum_{i \\in S_j} \\left(\\left(y_i - \\bar{y}_{(j)}\\right) + \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)\\right)^2 \\\\\n",
" & = \\sum_{j = 1}^m \\sum_{i \\in S_j} \\left(\\left(y_i - \\bar{y}_{(j)}\\right)^2 + 2 \\left(y_i - \\bar{y}_{(j)}\\right) \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right) + \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)^2\\right).\n",
"\\end{align*}\n",
"$$\n",
"\n",
"As is usual in these situations, the cross term vanishes, since\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"\\sum_{i \\in S_j} \\left(y_i - \\bar{y}_{(j)}\\right) \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)\n",
" & = \\sum_{i \\in S_j} \\left(y_i \\bar{y}_{(j)} - y_i \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal} - \\bar{y}_{(j)}^2 + \\bar{y}_{(j)} \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right) \\\\\n",
" & = \\bar{y}_{(j)} \\sum_{i \\in S_j} y_i - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal} \\sum_{i \\in S_j} y_i - n_j \\bar{y}_{(j)}^2 + n_j \\bar{y}_{(j)} \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal} \\\\\n",
" & = n_j \\bar{y}_{(j)}^2 - n_j \\bar{y}_{(j)} \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal} - n_j \\bar{y}_{(j)}^2 + n_j \\bar{y}_{(j)} \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal} \\\\\n",
" & = 0.\n",
"\\end{align*}\n",
"$$\n",
"\n",
"Therefore we may decompose the residual sum of squares as\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"RSS\n",
" & = \\sum_{j = 1}^m \\sum_{i \\in S_j} \\left(y_i - \\bar{y}_{(j)}\\right)^2 + \\sum_{j = 1}^m \\sum_{i \\in S_j} \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)^2 \\\\\n",
" & = \\sum_{j = 1}^m \\sum_{i \\in S_j} \\left(y_i - \\bar{y}_{(j)}\\right)^2 + \\sum_{j = 1}^m n_j \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)^2.\n",
"\\end{align*}\n",
"$$\n",
"\n",
"The important property of this decomposition is that the first sum does not depend on $\\mathbf{\\beta}$, so minimizing $RSS$ with respect to $\\mathbf{\\beta}$ is equivalent to minimizing the second sum. We see that this second sum can be written as\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"\\sum_{j = 1}^m n_j \\left(\\bar{y}_{(j)} - \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)^2\n",
" & = \\sum_{j = 1}^m \\left(\\sqrt{n_j} \\bar{y}_{(j)} - \\sqrt{n_j} \\mathbf{z}_j \\mathbf{\\beta}^{\\intercal}\\right)^2\n",
"\\end{align*},\n",
"$$\n",
"\n",
"which is exactly the residual sum of squares for regressing $\\sqrt{n_j} \\bar{y}_{(j)}$ on $\\sqrt{n_j} \\mathbf{z}_j$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"summ_reg_df = reg_df.groupby(('u', 'v', 'w')).y.mean().reset_index().iloc[shuffled_ixs].reset_index(drop=True).copy()\n",
"summ_reg_df['n'] = n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" <th>y</th>\n",
" <th>n</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0.425597</td>\n",
" <td>-2.173984</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>48</td>\n",
" <td>1</td>\n",
" <td>-0.993981</td>\n",
" <td>-4.174895</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>35</td>\n",
" <td>0</td>\n",
" <td>0.358156</td>\n",
" <td>1.252848</td>\n",
" <td>9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>19</td>\n",
" <td>1</td>\n",
" <td>-0.760298</td>\n",
" <td>-6.612355</td>\n",
" <td>17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>40</td>\n",
" <td>1</td>\n",
" <td>-0.688514</td>\n",
" <td>-4.379063</td>\n",
" <td>13</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w y n\n",
"0 0 0 0.425597 -2.173984 14\n",
"1 48 1 -0.993981 -4.174895 7\n",
"2 35 0 0.358156 1.252848 9\n",
"3 19 1 -0.760298 -6.612355 17\n",
"4 40 1 -0.688514 -4.379063 13"
]
},
"execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"summ_reg_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The design matrices for this summarized model are easy to construct using [`patsy`](https://patsy.readthedocs.org/en/latest/)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"y_summ, X_summ = dmatrices(\"\"\"\n",
" I(np.sqrt(n) * y) ~\n",
" np.sqrt(n) + I(np.sqrt(n) * u) + I(np.sqrt(n) * v) + I(np.sqrt(n) * w) - 1\n",
" \"\"\",\n",
" data=summ_reg_df)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we must remove `patsy`'s constant column for the intercept and replace it with `np.sqrt(n)`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"summ_ols = sm.OLS(y_summ, X_summ).fit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([-2.99965783, 0.09998571, -3.99899718, 2.00031673])"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"summ_ols.params"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the summarized regression produces the same parameter estimates as the full regression."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.allclose(full_ols.params, summ_ols.params)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Logistic Regression\n",
"\n",
"As a final example of adapting common methods to summarized data frames, we will show how to fit a logistic regression model on a summarized data set by maximum likelihood.\n",
"\n",
"We will use the model\n",
"\n",
"$$P(s = 1\\ |\\ w) = \\frac{1}{1 + \\exp(-\\mathbf{x} \\gamma^{\\intercal})}$$.\n",
"\n",
"As above, $\\mathbf{x}_i = [1\\ u_i\\ v_i\\ w_i]$. The true value of $\\gamma$ is"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"gamma = np.array([1., 0.01, -1., -2.])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now generate samples from this model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"X = dmatrix('u + v + w', data=df)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"p = pd.Series(sp.special.expit(np.dot(X, gamma)), name='p')\n",
"s = pd.Series(sp.stats.bernoulli.rvs(p), name='s')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"logit_df = pd.concat((s, p, df), axis=1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>s</th>\n",
" <th>p</th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>0.709963</td>\n",
" <td>97</td>\n",
" <td>0</td>\n",
" <td>0.537397</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0</td>\n",
" <td>0.092560</td>\n",
" <td>79</td>\n",
" <td>1</td>\n",
" <td>1.536383</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0</td>\n",
" <td>0.153211</td>\n",
" <td>44</td>\n",
" <td>1</td>\n",
" <td>1.074817</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1</td>\n",
" <td>0.923609</td>\n",
" <td>51</td>\n",
" <td>0</td>\n",
" <td>-0.491210</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0</td>\n",
" <td>0.062077</td>\n",
" <td>47</td>\n",
" <td>1</td>\n",
" <td>1.592646</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" s p u v w\n",
"0 1 0.709963 97 0 0.537397\n",
"1 0 0.092560 79 1 1.536383\n",
"2 0 0.153211 44 1 1.074817\n",
"3 1 0.923609 51 0 -0.491210\n",
"4 0 0.062077 47 1 1.592646"
]
},
"execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"logit_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We first fit the logistic regression model to the full data frame."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Optimization terminated successfully.\n",
" Current function value: 0.414221\n",
" Iterations 7\n"
]
}
],
"source": [
"full_logit = sm.Logit(s, X).fit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"const 0.965283\n",
"x1 0.009944\n",
"x2 -0.966797\n",
"x3 -1.990506\n",
"dtype: float64"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"full_logit.params"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see that the estimates are quite close to the true parameters.\n",
"\n",
"The technique used to adapt maximum likelihood estimation of logistic regression to the summarized data frame is quite elegant. The likelihood for the full data set is given by the fact that (given $u$, $v$, and $w$) $s$ is [Bernoulli distributed](https://en.wikipedia.org/wiki/Bernoulli_distribution) with\n",
"\n",
"$$s_i\\ |\\ \\mathbf{x}_i \\sim \\operatorname{Ber}\\left(\\frac{1}{1 + \\exp(-\\mathbf{x}_i \\gamma^{\\intercal})}\\right).$$\n",
"\n",
"\n",
"To derive the likelihood for the summarized data set, we count the number of successes (where $s = 1$) for each unique combination of features $\\mathbf{z}_j$, and denote this quantity $k_j$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"summ_logit_df = logit_df.groupby(('u', 'v', 'w')).s.sum().reset_index().iloc[shuffled_ixs].reset_index(drop=True).copy()\n",
"summ_logit_df = summ_logit_df.rename(columns={'s': 'k'})\n",
"summ_logit_df['n'] = n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>u</th>\n",
" <th>v</th>\n",
" <th>w</th>\n",
" <th>k</th>\n",
" <th>n</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0.425597</td>\n",
" <td>5</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>48</td>\n",
" <td>1</td>\n",
" <td>-0.993981</td>\n",
" <td>7</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>35</td>\n",
" <td>0</td>\n",
" <td>0.358156</td>\n",
" <td>8</td>\n",
" <td>9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>19</td>\n",
" <td>1</td>\n",
" <td>-0.760298</td>\n",
" <td>12</td>\n",
" <td>17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>40</td>\n",
" <td>1</td>\n",
" <td>-0.688514</td>\n",
" <td>9</td>\n",
" <td>13</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" u v w k n\n",
"0 0 0 0.425597 5 14\n",
"1 48 1 -0.993981 7 7\n",
"2 35 0 0.358156 8 9\n",
"3 19 1 -0.760298 12 17\n",
"4 40 1 -0.688514 9 13"
]
},
"execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"summ_logit_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, instead of each row representing a single Bernoulli trial (as in the full data frame), each row represents $n_j$ trials, so we have that $k_j$ is (conditionally) [Binomially distributed](https://en.wikipedia.org/wiki/Binomial_distribution) with\n",
"\n",
"$$k_j\\ |\\ \\mathbf{z}_j \\sim \\operatorname{Bin}\\left(n_j, \\frac{1}{1 + \\exp(-\\mathbf{z}_j \\gamma^{\\intercal})}\\right).$$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"summ_logit_X = dmatrix('u + v + w', data=summ_logit_df)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As I have shown in a [previous post](http://austinrochford.com/posts/2015-03-03-mle-python-statsmodels.html), we can use `statsmodels`' [`GenericLikelihoodModel`](http://statsmodels.sourceforge.net/devel/dev/generated/statsmodels.base.model.GenericLikelihoodModel.html) class to fit custom probability models by maximum likelihood. The model is implemented as follows."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"class SummaryLogit(GenericLikelihoodModel):\n",
" def __init__(self, endog, exog, n, **qwargs):\n",
" \"\"\"\n",
" endog is the number of successes\n",
" exog are the features\n",
" n are the number of trials\n",
" \"\"\"\n",
" self.n = n\n",
" \n",
" super(SummaryLogit, self).__init__(endog, exog, **qwargs)\n",
" \n",
" def nloglikeobs(self, gamma):\n",
" \"\"\"\n",
" gamma is the vector of regression coefficients\n",
" \n",
" returns the negative log likelihood of each of the observations for\n",
" the coefficients in gamma\n",
" \"\"\"\n",
" p = sp.special.expit(np.dot(self.exog, gamma))\n",
" \n",
" return -sp.stats.binom.logpmf(self.endog, self.n, p)\n",
" \n",
" def fit(self, start_params=None, maxiter=10000, maxfun=5000, **qwargs):\n",
" # wraps the GenericLikelihoodModel's fit method to set default start parameters\n",
" if start_params is None:\n",
" start_params = np.zeros(self.exog.shape[1])\n",
" \n",
" return super(SummaryLogit, self).fit(start_params=start_params,\n",
" maxiter=maxiter, maxfun=maxfun, **qwargs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Optimization terminated successfully.\n",
" Current function value: 1.317583\n",
" Iterations: 357\n",
" Function evaluations: 599\n"
]
}
],
"source": [
"summ_logit = SummaryLogit(summ_logit_df.k, summ_logit_X, summ_logit_df.n).fit()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, we get reasonable estimates of the regression coefficients, which are close to those obtained from the full data set."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"summ_logit.params"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"np.allclose(summ_logit.params, full_logit.params, rtol=10**-4)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# Conclusion\n",
"\n",
"Hopefully this introduction to the technique of summarizing data sets has proved useful and will allow you to explore medium data more easily in the future. We have only scratched the surface on the types of statistical techniques that can be adapted to work on summarized data sets, but with a bit of ingenuity, many of the ideas in this post can apply to other models."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment