{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pooled Classification\n",
    "\n",
    "A common workflow with longitudinal spatial data is to apply the same classification scheme to an attribute over different time periods. More specifically, one would like to keep the class breaks the same over each period and examine how the mass of the distribution changes over these classes in the different periods.\n",
    "\n",
    "The `Pooled` classifier supports this workflow."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import mapclassify as mc"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sample Data\n",
    "We construct a synthetic dataset composed of 20 cross-sectional units at three time points. Here the mean of the series is increasing over time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 20\n",
    "data = np.array([np.arange(n)+i*n for i in range(1,4)]).T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(20, 3)"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[20, 40, 60],\n",
       "       [21, 41, 61],\n",
       "       [22, 42, 62],\n",
       "       [23, 43, 63],\n",
       "       [24, 44, 64],\n",
       "       [25, 45, 65],\n",
       "       [26, 46, 66],\n",
       "       [27, 47, 67],\n",
       "       [28, 48, 68],\n",
       "       [29, 49, 69],\n",
       "       [30, 50, 70],\n",
       "       [31, 51, 71],\n",
       "       [32, 52, 72],\n",
       "       [33, 53, 73],\n",
       "       [34, 54, 74],\n",
       "       [35, 55, 75],\n",
       "       [36, 56, 76],\n",
       "       [37, 57, 77],\n",
       "       [38, 58, 78],\n",
       "       [39, 59, 79]])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Default: Quintiles\n",
    "The default is to apply a [vec](https://en.wikipedia.org/wiki/Vectorization_(mathematics)) operator to the data matrix and treat the observations as a single collection. Here the quantiles of the pooled data are obtained."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = mc.Pooled(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[20.00, 31.80] |    12\n",
       "(31.80, 43.60] |     8\n",
       "(43.60, 55.40] |     0\n",
       "(55.40, 67.20] |     0\n",
       "(67.20, 79.00] |     0\n",
       "\n",
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 31.80] |     0\n",
       "(31.80, 43.60] |     4\n",
       "(43.60, 55.40] |    12\n",
       "(55.40, 67.20] |     4\n",
       "(67.20, 79.00] |     0\n",
       "\n",
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 31.80] |     0\n",
       "(31.80, 43.60] |     0\n",
       "(43.60, 55.40] |     0\n",
       "(55.40, 67.20] |     8\n",
       "(67.20, 79.00] |    12"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the class definitions are identical with the exception of the lower bound in the first period. Since the first period contains the minimum value in the pooled series, that value defines the closed lower bound in the first period. In subsequent periods, the local minimums are all greater than the closed upper bound on the first interval - in other words the local minimums are not contained in the first class for the second and third periods. Following the [policy in mapclassify](https://github.com/pysal/mapclassify/blob/master/mapclassify/classifiers.py#L94), the lower bounds for the second and third periods are both set to `-inf` to indicate that their minimum values are not contained in the first class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = mc.Pooled(data, k=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([15,  5,  0,  0])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res.col_classifiers[0].counts\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  0,  5, 15])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res.col_classifiers[-1].counts\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([15, 15, 15, 15])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res.global_classifier.counts\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[20.00, 34.75] |    15\n",
       "(34.75, 49.50] |     5\n",
       "(49.50, 64.25] |     0\n",
       "(64.25, 79.00] |     0\n",
       "\n",
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 34.75] |     0\n",
       "(34.75, 49.50] |    10\n",
       "(49.50, 64.25] |    10\n",
       "(64.25, 79.00] |     0\n",
       "\n",
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 34.75] |     0\n",
       "(34.75, 49.50] |     0\n",
       "(49.50, 64.25] |     5\n",
       "(64.25, 79.00] |    15"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Extract the pooled classification objects for each column"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "c0, c1, c2 = res.col_classifiers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[20.00, 34.75] |    15\n",
       "(34.75, 49.50] |     5\n",
       "(49.50, 64.25] |     0\n",
       "(64.25, 79.00] |     0"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Compare to the unrestricted classifier for the first column"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Quantiles             \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[20.00, 24.75] |     5\n",
       "(24.75, 29.50] |     5\n",
       "(29.50, 34.25] |     5\n",
       "(34.25, 39.00] |     5"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mc.Quantiles(c0.y, k=4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and the last column comparisions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Quantiles      \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 34.75] |     0\n",
       "(34.75, 49.50] |     0\n",
       "(49.50, 64.25] |     5\n",
       "(64.25, 79.00] |    15"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Quantiles             \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[60.00, 64.75] |     5\n",
       "(64.75, 69.50] |     5\n",
       "(69.50, 74.25] |     5\n",
       "(74.25, 79.00] |     5"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mc.Quantiles(c2.y, k=4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Non-default classifier: BoxPlot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = mc.Pooled(data, classifier='BoxPlot', hinge=1.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled BoxPlot          \n",
       "\n",
       "    Interval       Count\n",
       "------------------------\n",
       "(  -inf,  -9.50] |     0\n",
       "( -9.50,  34.75] |    15\n",
       "( 34.75,  49.50] |     5\n",
       "( 49.50,  64.25] |     0\n",
       "( 64.25, 108.50] |     0\n",
       "\n",
       "Pooled BoxPlot          \n",
       "\n",
       "    Interval       Count\n",
       "------------------------\n",
       "(  -inf,  -9.50] |     0\n",
       "( -9.50,  34.75] |     0\n",
       "( 34.75,  49.50] |    10\n",
       "( 49.50,  64.25] |    10\n",
       "( 64.25, 108.50] |     0\n",
       "\n",
       "Pooled BoxPlot          \n",
       "\n",
       "    Interval       Count\n",
       "------------------------\n",
       "(  -inf,  -9.50] |     0\n",
       "( -9.50,  34.75] |     0\n",
       "( 34.75,  49.50] |     0\n",
       "( 49.50,  64.25] |     5\n",
       "( 64.25, 108.50] |    15"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ -9.5 ,  34.75,  49.5 ,  64.25, 108.5 ])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res.col_classifiers[0].bins"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "c0, c1, c2 = res.col_classifiers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c0.yb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "c00 = mc.BoxPlot(c0.y, hinge=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4])"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c00.yb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "BoxPlot               \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, -3.75] |     0\n",
       "(-3.75, 24.75] |     5\n",
       "(24.75, 29.50] |     5\n",
       "(29.50, 34.25] |     5\n",
       "(34.25, 62.75] |     5"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c00"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled BoxPlot          \n",
       "\n",
       "    Interval       Count\n",
       "------------------------\n",
       "(  -inf,  -9.50] |     0\n",
       "( -9.50,  34.75] |    15\n",
       "( 34.75,  49.50] |     5\n",
       "( 49.50,  64.25] |     0\n",
       "( 64.25, 108.50] |     0"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Non-default classifier: FisherJenks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = mc.Pooled(data, classifier='FisherJenks', k=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled FisherJenks    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[20.00, 31.00] |    12\n",
       "(31.00, 43.00] |     8\n",
       "(43.00, 55.00] |     0\n",
       "(55.00, 67.00] |     0\n",
       "(67.00, 79.00] |     0\n",
       "\n",
       "Pooled FisherJenks    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 31.00] |     0\n",
       "(31.00, 43.00] |     4\n",
       "(43.00, 55.00] |    12\n",
       "(55.00, 67.00] |     4\n",
       "(67.00, 79.00] |     0\n",
       "\n",
       "Pooled FisherJenks    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "( -inf, 31.00] |     0\n",
       "(31.00, 43.00] |     0\n",
       "(43.00, 55.00] |     0\n",
       "(55.00, 67.00] |     8\n",
       "(67.00, 79.00] |    12"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "FisherJenks           \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[20.00, 23.00] |     4\n",
       "(23.00, 27.00] |     4\n",
       "(27.00, 31.00] |     4\n",
       "(31.00, 35.00] |     4\n",
       "(35.00, 39.00] |     4"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c0, c1, c2 = res.col_classifiers\n",
    "mc.FisherJenks(c0.y, k=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Non-default classifier: MaximumBreaks\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[20, 40, 60],\n",
       "       [10, 10, 10],\n",
       "       [22, 42, 62],\n",
       "       [23, 43, 63],\n",
       "       [24, 44, 64],\n",
       "       [25, 45, 65],\n",
       "       [26, 46, 66],\n",
       "       [27, 47, 67],\n",
       "       [28, 48, 68],\n",
       "       [29, 49, 10],\n",
       "       [30, 50, 70],\n",
       "       [31, 51, 71],\n",
       "       [32, 52, 72],\n",
       "       [33, 53, 73],\n",
       "       [34, 54, 74],\n",
       "       [35, 55, 75],\n",
       "       [36, 56, 76],\n",
       "       [37, 57, 77],\n",
       "       [38, 58, 78],\n",
       "       [39, 59, 79]])"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[1, 0] = 10\n",
    "data[1, 1] = 10\n",
    "data[1, 2] = 10\n",
    "data[9, 2] = 10\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = mc.Pooled(data, classifier='MaximumBreaks', k=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled MaximumBreaks  \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 15.00] |     1\n",
       "(15.00, 21.00] |     1\n",
       "(21.00, 41.00] |    18\n",
       "(41.00, 61.00] |     0\n",
       "(61.00, 79.00] |     0\n",
       "\n",
       "Pooled MaximumBreaks  \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 15.00] |     1\n",
       "(15.00, 21.00] |     0\n",
       "(21.00, 41.00] |     1\n",
       "(41.00, 61.00] |    18\n",
       "(61.00, 79.00] |     0\n",
       "\n",
       "Pooled MaximumBreaks  \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 15.00] |     2\n",
       "(15.00, 21.00] |     0\n",
       "(21.00, 41.00] |     0\n",
       "(41.00, 61.00] |     1\n",
       "(61.00, 79.00] |    17"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "c0, c1, c2 = res.col_classifiers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled MaximumBreaks  \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 15.00] |     1\n",
       "(15.00, 21.00] |     1\n",
       "(21.00, 41.00] |    18\n",
       "(41.00, 61.00] |     0\n",
       "(61.00, 79.00] |     0"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Insufficient number of unique diffs. Breaks are random.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "MaximumBreaks         \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 15.00] |     1\n",
       "(15.00, 21.00] |     1\n",
       "(21.00, 22.50] |     1\n",
       "(22.50, 28.50] |     6\n",
       "(28.50, 39.00] |    11"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mc.MaximumBreaks(c0.y, k=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = mc.Pooled(data, classifier='UserDefined', bins=mc.Quantiles(data[:,-1]).bins)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |    20\n",
       "(62.80, 66.60] |     0\n",
       "(66.60, 71.40] |     0\n",
       "(71.40, 75.20] |     0\n",
       "(75.20, 79.00] |     0\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |    20\n",
       "(62.80, 66.60] |     0\n",
       "(66.60, 71.40] |     0\n",
       "(71.40, 75.20] |     0\n",
       "(75.20, 79.00] |     0\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |     4\n",
       "(62.80, 66.60] |     4\n",
       "(66.60, 71.40] |     4\n",
       "(71.40, 75.20] |     4\n",
       "(75.20, 79.00] |     4"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Quantiles             \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |     4\n",
       "(62.80, 66.60] |     4\n",
       "(66.60, 71.40] |     4\n",
       "(71.40, 75.20] |     4\n",
       "(75.20, 79.00] |     4"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mc.Quantiles(data[:,-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([60, 10, 62, 63, 64, 65, 66, 67, 68, 10, 70, 71, 72, 73, 74, 75, 76,\n",
       "       77, 78, 79])"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[:,-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pinning the pooling\n",
    "\n",
    "Another option is to specify a specific subperiod as the definition for the classes in the pooling.\n",
    "\n",
    "### Pinning to the last period\n",
    "\n",
    "As an example, we can use the quintles from the third period to defined the pooled classifier:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "pinned = mc.Pooled(data, classifier='UserDefined', bins=mc.Quantiles(data[:,-1]).bins)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |    20\n",
       "(62.80, 66.60] |     0\n",
       "(66.60, 71.40] |     0\n",
       "(71.40, 75.20] |     0\n",
       "(75.20, 79.00] |     0\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |    20\n",
       "(62.80, 66.60] |     0\n",
       "(66.60, 71.40] |     0\n",
       "(71.40, 75.20] |     0\n",
       "(75.20, 79.00] |     0\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |     4\n",
       "(62.80, 66.60] |     4\n",
       "(66.60, 71.40] |     4\n",
       "(71.40, 75.20] |     4\n",
       "(75.20, 79.00] |     4"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pinned"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "UserDefined           \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 62.80] |    44\n",
       "(62.80, 66.60] |     4\n",
       "(66.60, 71.40] |     4\n",
       "(71.40, 75.20] |     4\n",
       "(75.20, 79.00] |     4"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pinned.global_classifier"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pinning to the first period"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "pinned = mc.Pooled(data, classifier='UserDefined', bins=mc.Quantiles(data[:,0]).bins)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pooled Classifier\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 23.80] |     4\n",
       "(23.80, 27.60] |     4\n",
       "(27.60, 31.40] |     4\n",
       "(31.40, 35.20] |     4\n",
       "(35.20, 39.00] |     4\n",
       "(39.00, 79.00] |     0\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 23.80] |     1\n",
       "(23.80, 27.60] |     0\n",
       "(27.60, 31.40] |     0\n",
       "(31.40, 35.20] |     0\n",
       "(35.20, 39.00] |     0\n",
       "(39.00, 79.00] |    19\n",
       "\n",
       "Pooled UserDefined    \n",
       "\n",
       "   Interval      Count\n",
       "----------------------\n",
       "[10.00, 23.80] |     2\n",
       "(23.80, 27.60] |     0\n",
       "(27.60, 31.40] |     0\n",
       "(31.40, 35.20] |     0\n",
       "(35.20, 39.00] |     0\n",
       "(39.00, 79.00] |    18"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pinned"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the quintiles for the first period, by definition, contain all the values from that period, they do not bound the larger values in subsequent period. Following the [mapclassify policy](https://github.com/pysal/mapclassify/blob/master/mapclassify/classifiers.py#L569), an additional class is added to contain all values in the pooled series."
   ]
  }
 ],
 "metadata": {
  "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.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
