<NME> More Mixed Logit--Heteroskedasticity and Nesting.ipynb
<BEF> ADDFILE
<MSG> Added two new example notebooks. One for converting long-format dataframes to wide-format, and the other for estimating still more types of mixed logit models.

<DFF> @@ -0,0 +1,1120 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# More Mixed Logit\n",
+    "The purpose of this notebook is to prodvide more examples of estimating Normal Error Component Mixed Logit Models. The types of models to be estimated in this notebook include models that use mixing distributions to account for heteroskedasticity and/or non-zero correlations between the error terms of one's various utility equations.\n",
+    "\n",
+    "As in some of the other example notebooks, the dataset being used is the \"Travel Mode Choice\" dataset from Greene and Hensher. It is described on the statsmodels <a href=\"http://statsmodels.sourceforge.net/0.6.0/datasets/generated/modechoice.html\">website</a>, and their description is reproduced below in full. The basic specification to be estimated will come from the example given in Econometric Analysis by William H. Greene (2011), section 23.11.7.\n",
+    "\n",
+    "<pre>\n",
+    "    The data, collected as part of a 1987 intercity mode choice study, are a sub-sample of 210 non-business\n",
+    "    trips between Sydney, Canberra and Melbourne in which the traveler chooses a mode from four alternatives\n",
+    "    (plane, car, bus and train). The sample, 840 observations, is choice based with over-sampling of the\n",
+    "    less popular modes (plane, train and bus) and under-sampling of the more popular mode, car. The level of\n",
+    "    service data was derived from highway and transport networks in Sydney, Melbourne, non-metropolitan N.S.W.\n",
+    "    and Victoria, including the Australian Capital Territory.\n",
+    "    \n",
+    "    Number of observations: 840 Observations On 4 Modes for 210 Individuals.\n",
+    "    Number of variables: 8\n",
+    "    Variable name definitions::\n",
+    "\n",
+    "        individual = 1 to 210\n",
+    "        mode =\n",
+    "            1 - air\n",
+    "            2 - train\n",
+    "            3 - bus\n",
+    "            4 - car\n",
+    "        choice =\n",
+    "            0 - no\n",
+    "            1 - yes\n",
+    "        ttme = terminal waiting time for plane, train and bus (minutes); 0\n",
+    "               for car.\n",
+    "        invc = in vehicle cost for all stages (dollars).\n",
+    "        invt = travel time (in-vehicle time) for all stages (minutes).\n",
+    "        gc = generalized cost measure:invc+(invt*value of travel time savings)\n",
+    "            (dollars).\n",
+    "        hinc = household income ($1000s).\n",
+    "        psize = traveling group size in mode chosen (number).\n",
+    "        \n",
+    "    \n",
+    "    Source\n",
+    "\n",
+    "    Greene, W.H. and D. Hensher (1997) Multinomial logit and discrete choice models in Greene, W. H. (1997)\n",
+    "    LIMDEP version 7.0 user’s manual revised, Plainview, New York econometric software, Inc. Download from\n",
+    "    on-line complements to Greene, W.H. (2011) Econometric Analysis, Prentice Hall, 7th Edition (data table\n",
+    "    F18-2) http://people.stern.nyu.edu/wgreene/Text/Edition7/TableF18-2.csv\n",
+    "\n",
+    "</pre>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Load needed packages"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "# Note the ordered dictionaries are used to store our\n",
+    "# model specifications\n",
+    "from collections import OrderedDict\n",
+    "\n",
+    "# Pandas is used for data input/output\n",
+    "import pandas as pd\n",
+    "# Numpy is used for vectorized math operations\n",
+    "import numpy as np\n",
+    "# Statsmodels is used to retrieve the dataset\n",
+    "import statsmodels.datasets\n",
+    "\n",
+    "# Pylogit is used to estimate the model\n",
+    "import pylogit as pl"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Load the dataset"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "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>individual</th>\n",
+       "      <th>mode</th>\n",
+       "      <th>choice</th>\n",
+       "      <th>ttme</th>\n",
+       "      <th>invc</th>\n",
+       "      <th>invt</th>\n",
+       "      <th>gc</th>\n",
+       "      <th>hinc</th>\n",
+       "      <th>psize</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>69</td>\n",
+       "      <td>59</td>\n",
+       "      <td>100</td>\n",
+       "      <td>70</td>\n",
+       "      <td>35</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>1</td>\n",
+       "      <td>2</td>\n",
+       "      <td>0</td>\n",
+       "      <td>34</td>\n",
+       "      <td>31</td>\n",
+       "      <td>372</td>\n",
+       "      <td>71</td>\n",
+       "      <td>35</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>1</td>\n",
+       "      <td>3</td>\n",
+       "      <td>0</td>\n",
+       "      <td>35</td>\n",
+       "      <td>25</td>\n",
+       "      <td>417</td>\n",
+       "      <td>70</td>\n",
+       "      <td>35</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>1</td>\n",
+       "      <td>4</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>10</td>\n",
+       "      <td>180</td>\n",
+       "      <td>30</td>\n",
+       "      <td>35</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>2</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>64</td>\n",
+       "      <td>58</td>\n",
+       "      <td>68</td>\n",
+       "      <td>68</td>\n",
+       "      <td>30</td>\n",
+       "      <td>2</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "   individual  mode  choice  ttme  invc  invt  gc  hinc  psize\n",
+       "0           1     1       0    69    59   100  70    35      1\n",
+       "1           1     2       0    34    31   372  71    35      1\n",
+       "2           1     3       0    35    25   417  70    35      1\n",
+       "3           1     4       1     0    10   180  30    35      1\n",
+       "4           2     1       0    64    58    68  68    30      2"
+      ]
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Access the dataset\n",
+    "mode_data = statsmodels.datasets.modechoice.load_pandas()\n",
+    "# Get a pandas dataframe of the mode choice data\n",
+    "mode_df = mode_data[\"data\"]\n",
+    "# Look at a few rows of the data\n",
+    "mode_df.head()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Specify and Estimate a Multinomial Logit (MNL) Model\n",
+    "Even though we want to estimate a mixed logit model, we first start by speficying a basic MNL model. This will give us \"good\" starting values for the mixed logit model.\n",
+    "\n",
+    "The utility equations used by Greene are as follows. Note that $i$ refers to a particular individual and $j$ refers to a particular travel mode. Moreover, $d_{i, \\textrm{condition}}$ is an indicator that equals 1 for individual $i$ when the condition is true.<br><br>\n",
+    "<font size=4>$\\begin{align}\n",
+    "U_{ij} &= \\alpha _{\\textrm{air}} d_{i,\\ j=\\textrm{air}} + \n",
+    "          \\alpha _{\\textrm{train}} d_{i,\\ j=\\textrm{train}} +\n",
+    "          \\alpha _{\\textrm{bus}} d_{i,\\ j=\\textrm{bus}} + \\\\\n",
+    "          &\\quad \\ \\beta _{\\textrm{generalized_cost}} \\textrm{GC}_{ij} +\n",
+    "          \\beta _{\\textrm{terminal_time}} \\textrm{TTME}_{ij} +\n",
+    "          \\beta _{\\textrm{household_income}} d_{i,\\ j=\\textrm{air}} \\textrm{HINC}_{i} +\n",
+    "          \\epsilon _{ij}\n",
+    "\\end{align}\n",
+    "$</font>\n",
+    "<br><br>In other words, there is an alternative-specific-constant (i.e. an intercept) for the air, train, and bus modes, and the car is used as the reference mode. Moreover, the alternative-specific variables (i.e. the generalized cost and terminal time variables) are specified has having generic effects on all modes. That is, the impact of a one-minute increase in terminal time or a 1\\$ increase in \"generalized cost\" on the utility of a given mode is a-priori assumed to be the same for all modes. In contrast to the alternative-specific variables, household income is an individual characteristic and it is a-priori assumed to only affect the utility of traveling by air."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "# Initialize the Ordered Dictionaries to store the model\n",
+    "# specification and parameter names\n",
+    "specification_dict = OrderedDict()\n",
+    "name_dict = OrderedDict()\n",
+    "\n",
+    "# Add the variables to the specification and name dictionaries.\n",
+    "specification_dict[\"intercept\"] = [1, 2, 3]\n",
+    "name_dict[\"intercept\"] = [\"ASC Air\", \"ASC Train\", \"ASC Bus\"]\n",
+    "\n",
+    "specification_dict[\"gc\"] = [[1, 2, 3, 4]]\n",
+    "name_dict[\"gc\"] = [\"Generalized Cost (all modes)\"]\n",
+    "\n",
+    "specification_dict[\"ttme\"] = [[1, 2, 3, 4]]\n",
+    "name_dict[\"ttme\"] = [\"Terminal Time (all modes)\"]\n",
+    "\n",
+    "specification_dict[\"hinc\"] = [1]\n",
+    "name_dict[\"hinc\"] = [\"Household Income (air mode)\"]\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Log-likelihood at zero: -291.1218\n",
+      "Initial Log-likelihood: -291.1218\n",
+      "Estimation Time: 0.01 seconds.\n",
+      "Final log-likelihood: -199.1284\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/Users/timothyb0912/anaconda/lib/python2.7/site-packages/scipy/optimize/_minimize.py:382: RuntimeWarning: Method BFGS does not use Hessian information (hess).\n",
+      "  RuntimeWarning)\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table class=\"simpletable\">\n",
+       "<caption>Multinomial Logit Model Regression Results</caption>\n",
+       "<tr>\n",
+       "  <th>Dep. Variable:</th>         <td>choice</td>          <th>  No. Observations:  </th>    <td>210</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Model:</th>         <td>Multinomial Logit Model</td> <th>  Df Residuals:      </th>    <td>204</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Method:</th>                  <td>MLE</td>           <th>  Df Model:          </th>     <td>6</td>   \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Date:</th>             <td>Sat, 19 Nov 2016</td>     <th>  Pseudo R-squ.:     </th>   <td>0.316</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Time:</th>                 <td>19:01:17</td>         <th>  Pseudo R-bar-squ.: </th>   <td>0.295</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>converged:</th>              <td>True</td>           <th>  Log-Likelihood:    </th> <td>-199.128</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th> </th>                         <td> </td>            <th>  LL-Null:           </th> <td>-291.122</td>\n",
+       "</tr>\n",
+       "</table>\n",
+       "<table class=\"simpletable\">\n",
+       "<tr>\n",
+       "                <td></td>                  <th>coef</th>     <th>std err</th>      <th>z</th>      <th>P>|z|</th> <th>[95.0% Conf. Int.]</th> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Air</th>                      <td>    5.2074</td> <td>    0.779</td> <td>    6.684</td> <td> 0.000</td> <td>    3.681     6.734</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Train</th>                    <td>    3.8690</td> <td>    0.443</td> <td>    8.731</td> <td> 0.000</td> <td>    3.001     4.738</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Bus</th>                      <td>    3.1632</td> <td>    0.450</td> <td>    7.025</td> <td> 0.000</td> <td>    2.281     4.046</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Generalized Cost (all modes)</th> <td>   -0.0155</td> <td>    0.004</td> <td>   -3.517</td> <td> 0.000</td> <td>   -0.024    -0.007</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Terminal Time (all modes)</th>    <td>   -0.0961</td> <td>    0.010</td> <td>   -9.207</td> <td> 0.000</td> <td>   -0.117    -0.076</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Household Income (air mode)</th>  <td>    0.0133</td> <td>    0.010</td> <td>    1.295</td> <td> 0.195</td> <td>   -0.007     0.033</td>\n",
+       "</tr>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "<class 'statsmodels.iolib.summary.Summary'>\n",
+       "\"\"\"\n",
+       "                     Multinomial Logit Model Regression Results                    \n",
+       "===================================================================================\n",
+       "Dep. Variable:                      choice   No. Observations:                  210\n",
+       "Model:             Multinomial Logit Model   Df Residuals:                      204\n",
+       "Method:                                MLE   Df Model:                            6\n",
+       "Date:                     Sat, 19 Nov 2016   Pseudo R-squ.:                   0.316\n",
+       "Time:                             19:01:17   Pseudo R-bar-squ.:               0.295\n",
+       "converged:                            True   Log-Likelihood:               -199.128\n",
+       "                                             LL-Null:                      -291.122\n",
+       "================================================================================================\n",
+       "                                   coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
+       "------------------------------------------------------------------------------------------------\n",
+       "ASC Air                          5.2074      0.779      6.684      0.000         3.681     6.734\n",
+       "ASC Train                        3.8690      0.443      8.731      0.000         3.001     4.738\n",
+       "ASC Bus                          3.1632      0.450      7.025      0.000         2.281     4.046\n",
+       "Generalized Cost (all modes)    -0.0155      0.004     -3.517      0.000        -0.024    -0.007\n",
+       "Terminal Time (all modes)       -0.0961      0.010     -9.207      0.000        -0.117    -0.076\n",
+       "Household Income (air mode)      0.0133      0.010      1.295      0.195        -0.007     0.033\n",
+       "================================================================================================\n",
+       "\"\"\""
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Estimate the MNL model\n",
+    "# Initialize the model object\n",
+    "mnl_model = pl.create_choice_model(data=mode_df,\n",
+    "                                   alt_id_col=\"mode\",\n",
+    "                                   obs_id_col=\"individual\",\n",
+    "                                   choice_col=\"choice\",\n",
+    "                                   specification=specification_dict,\n",
+    "                                   model_type=\"MNL\",\n",
+    "                                   names=name_dict)\n",
+    "\n",
+    "# Create the initial values for the parameters\n",
+    "# being estimated\n",
+    "num_params = 6\n",
+    "initial_values = np.zeros(num_params)\n",
+    "\n",
+    "# Estimate the mnl_model\n",
+    "mnl_model.fit_mle(initial_values)\n",
+    "\n",
+    "# View the estimation results\n",
+    "mnl_model.get_statsmodels_summary()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Estimate a Mixed Logit Model with heteroskedastic errors\n",
+    "One way to allow the variances of the utilities for the various alternatives to be different is to add a mean zero normal error component to each utility. One's utility equations would then be as follows:\n",
+    "<font size=4>$\\begin{align}\n",
+    "U_{ij} &= \\alpha _{\\textrm{air}} d_{i,\\ j=\\textrm{air}} + \n",
+    "          \\alpha _{\\textrm{train}} d_{i,\\ j=\\textrm{train}} +\n",
+    "          \\alpha _{\\textrm{bus}} d_{i,\\ j=\\textrm{bus}} + \\\\\n",
+    "          &\\quad \\ \\beta _{\\textrm{generalized_cost}} \\textrm{GC}_{ij} +\n",
+    "          \\beta _{\\textrm{terminal_time}} \\textrm{TTME}_{ij} +\n",
+    "          \\beta _{\\textrm{household_income}} d_{i,\\ j=\\textrm{air}} \\textrm{HINC}_{i} +\\\\\n",
+    "          &\\quad \\ \\sigma_{\\textrm{air}} d_{i,\\ j=\\textrm{air}} \\eta_{ij} + \\sigma_{\\textrm{train}} d_{i,\\ j=\\textrm{train}} \\eta_{ij} + \\sigma_{\\textrm{bus}} d_{i,\\ j=\\textrm{bus}} \\eta_{ij} + \\sigma_{\\textrm{car}} d_{i,\\ j=\\textrm{car}} \\eta_{ij} + \\epsilon_{ij}\\\\\n",
+    "\\textrm{where }& \\eta_{ij} \\sim N\\left(0, 1\\right)\n",
+    "\\end{align}\n",
+    "$</font><br><br>\n",
+    "There are two things to note about the utility equations above. First, as noted by Walker et al. (2007) not all of the $\\sigma_j$'s are identifiable. As demonstrated below, this will be resolved by constraining the smallest $\\sigma_j$ to zero. Secondly, note that the utility equations above are formally equivalent to treating this as a random-coefficients model, where we view the alternative specific constants as being randomly distributed. This can be seen by re-writing the utility equations as follows:\n",
+    "<font size=4>$\\begin{align}\n",
+    "U_{ij} &= \\beta _{\\textrm{generalized_cost}} \\textrm{GC}_{ij} +\n",
+    "          \\beta _{\\textrm{terminal_time}} \\textrm{TTME}_{ij} +\n",
+    "          \\beta _{\\textrm{household_income}} d_{i,\\ j=\\textrm{air}} \\textrm{HINC}_{i} +\\\\\n",
+    "          &\\quad \\ \\sigma_{\\textrm{air}} d_{i,\\ j=\\textrm{air}} \\tilde{\\eta}_{ij} + \\sigma_{\\textrm{train}} d_{i,\\ j=\\textrm{train}} \\tilde{\\eta}_{ij} + \\sigma_{\\textrm{bus}} d_{i,\\ j=\\textrm{bus}} \\tilde{\\eta}_{ij} + \\sigma_{\\textrm{car}} d_{i,\\ j=\\textrm{car}} \\tilde{\\eta}_{ij} + \\epsilon_{ij}\\\\\n",
+    "\\textrm{where }& \\tilde{\\eta}_{ij} \\sim N\\left(\\alpha _{j}, 1\\right)\\\\\n",
+    "          &\\quad \\ j \\in \\left\\lbrace \\textrm{air, train, bus, car}\\right\\rbrace\\\\\n",
+    "          &\\quad \\ \\alpha _{\\textrm{car}} = 0\n",
+    "\\end{align}\n",
+    "$</font><br><br>\n",
+    "From this perspective, using a mixed-logit model to account for heteroskedasticity is equivalent to using a mixed-logit model where the alternative-specific constants are viewed as being randomly distributed throughout the population.\n",
+    "\n",
+    "Programmatically, PyLogit implements mixed logit models as random-coefficients models, so we will use this second viewpoint to specify the model to be estimated. \n",
+    "\n",
+    "In particular, we will instruct PyLogit to treat the alternative specific constants as normally distributed random variables, where we will estimate the mean and standard deviations of the distributions. Note that in order to estimate the $\\sigma_{\\textrm{car}}$ of the car alternative, we need to have a variable for the alternative specific constant of the car. We will therefore add the car to the intercept specification, but we will then constrain it to zero during estimation (and as noted in the equation above).\n",
+    "\n",
+    "As in Walker et al. (2007), we will first attempt to estimate all the standard deviations. Then (for identification purposes) we will re-estimate the model, constraining the smallest standard deviation from the first estimation.\n",
+    "\n",
+    "Sources:<br>\n",
+    "Joan L. Walker, Moshe Ben-Akiva, and Denis Bolduc. \"Identification of parameters in normal error component logit-mixture (NECLM) models.\" Journal of Applied Econometrics, 22(6):1095–1125, September 2007. ISSN 1099-1255. doi: 10.1002/jae.971. URL http://onlinelibrary.wiley. com/doi/10.1002/jae.971/abstract."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Log-likelihood at zero: -291.1218\n",
+      "Initial Log-likelihood: -199.1284\n",
+      "Estimation Time: 4.66 seconds.\n",
+      "Final log-likelihood: -195.7015\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table class=\"simpletable\">\n",
+       "<caption>Mixed Logit Model Regression Results</caption>\n",
+       "<tr>\n",
+       "  <th>Dep. Variable:</th>      <td>choice</td>       <th>  No. Observations:  </th>    <td>210</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Model:</th>         <td>Mixed Logit Model</td> <th>  Df Residuals:      </th>    <td>199</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Method:</th>               <td>MLE</td>        <th>  Df Model:          </th>    <td>11</td>   \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Date:</th>          <td>Sat, 19 Nov 2016</td>  <th>  Pseudo R-squ.:     </th>   <td>0.328</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Time:</th>              <td>19:01:22</td>      <th>  Pseudo R-bar-squ.: </th>   <td>0.290</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>converged:</th>           <td>False</td>       <th>  Log-Likelihood:    </th> <td>-195.701</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th> </th>                      <td> </td>         <th>  LL-Null:           </th> <td>-291.122</td>\n",
+       "</tr>\n",
+       "</table>\n",
+       "<table class=\"simpletable\">\n",
+       "<tr>\n",
+       "                <td></td>                  <th>coef</th>     <th>std err</th>      <th>z</th>      <th>P>|z|</th> <th>[95.0% Conf. Int.]</th> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Air</th>                      <td>    4.6890</td> <td>    1.503</td> <td>    3.119</td> <td> 0.002</td> <td>    1.743     7.635</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Train</th>                    <td>    5.2413</td> <td>    1.113</td> <td>    4.708</td> <td> 0.000</td> <td>    3.059     7.423</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Bus</th>                      <td>    4.2436</td> <td>    1.063</td> <td>    3.991</td> <td> 0.000</td> <td>    2.159     6.328</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Car</th>                      <td>         0</td> <td>      nan</td> <td>      nan</td> <td>   nan</td> <td>      nan       nan</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Generalized Cost (all modes)</th> <td>   -0.0333</td> <td>    0.010</td> <td>   -3.274</td> <td> 0.001</td> <td>   -0.053    -0.013</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Terminal Time (all modes)</th>    <td>   -0.1156</td> <td>    0.019</td> <td>   -6.126</td> <td> 0.000</td> <td>   -0.153    -0.079</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Household Income (air mode)</th>  <td>    0.0381</td> <td>    0.025</td> <td>    1.497</td> <td> 0.135</td> <td>   -0.012     0.088</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Air</th>                <td>   -3.3812</td> <td>    1.038</td> <td>   -3.257</td> <td> 0.001</td> <td>   -5.416    -1.347</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Train</th>              <td>    0.0660</td> <td>    4.236</td> <td>    0.016</td> <td> 0.988</td> <td>   -8.237     8.369</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Bus</th>                <td>   -0.0380</td> <td>    5.384</td> <td>   -0.007</td> <td> 0.994</td> <td>  -10.591    10.515</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Car</th>                <td>    0.3973</td> <td>    2.326</td> <td>    0.171</td> <td> 0.864</td> <td>   -4.162     4.957</td>\n",
+       "</tr>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "<class 'statsmodels.iolib.summary.Summary'>\n",
+       "\"\"\"\n",
+       "                     Mixed Logit Model Regression Results                     \n",
+       "==============================================================================\n",
+       "Dep. Variable:                 choice   No. Observations:                  210\n",
+       "Model:              Mixed Logit Model   Df Residuals:                      199\n",
+       "Method:                           MLE   Df Model:                           11\n",
+       "Date:                Sat, 19 Nov 2016   Pseudo R-squ.:                   0.328\n",
+       "Time:                        19:01:22   Pseudo R-bar-squ.:               0.290\n",
+       "converged:                      False   Log-Likelihood:               -195.701\n",
+       "                                        LL-Null:                      -291.122\n",
+       "================================================================================================\n",
+       "                                   coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
+       "------------------------------------------------------------------------------------------------\n",
+       "ASC Air                          4.6890      1.503      3.119      0.002         1.743     7.635\n",
+       "ASC Train                        5.2413      1.113      4.708      0.000         3.059     7.423\n",
+       "ASC Bus                          4.2436      1.063      3.991      0.000         2.159     6.328\n",
+       "ASC Car                               0        nan        nan        nan           nan       nan\n",
+       "Generalized Cost (all modes)    -0.0333      0.010     -3.274      0.001        -0.053    -0.013\n",
+       "Terminal Time (all modes)       -0.1156      0.019     -6.126      0.000        -0.153    -0.079\n",
+       "Household Income (air mode)      0.0381      0.025      1.497      0.135        -0.012     0.088\n",
+       "Sigma ASC Air                   -3.3812      1.038     -3.257      0.001        -5.416    -1.347\n",
+       "Sigma ASC Train                  0.0660      4.236      0.016      0.988        -8.237     8.369\n",
+       "Sigma ASC Bus                   -0.0380      5.384     -0.007      0.994       -10.591    10.515\n",
+       "Sigma ASC Car                    0.3973      2.326      0.171      0.864        -4.162     4.957\n",
+       "================================================================================================\n",
+       "\"\"\""
+      ]
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Add the intercept for car to the specification dictionary\n",
+    "heteroskedastic_specification = OrderedDict()\n",
+    "heteroskedastic_names = OrderedDict()\n",
+    "\n",
+    "heteroskedastic_specification[\"intercept\"] = [1, 2, 3, 4]\n",
+    "heteroskedastic_names[\"intercept\"] = [\"ASC Air\", \"ASC Train\", \"ASC Bus\", \"ASC Car\"]\n",
+    "\n",
+    "for key in specification_dict:\n",
+    "    if key != \"intercept\":\n",
+    "        heteroskedastic_specification[key] = specification_dict[key]\n",
+    "        heteroskedastic_names[key] = name_dict[key]\n",
+    "\n",
+    "# Create a list of the variables whose standard deviations\n",
+    "# are to be estimated\n",
+    "mixing_variables = heteroskedastic_names[\"intercept\"]\n",
+    "\n",
+    "heteroskedastic_model_0 = pl.create_choice_model(data=mode_df,\n",
+    "                                                 alt_id_col=\"mode\",\n",
+    "                                                 obs_id_col=\"individual\",\n",
+    "                                                 choice_col=\"choice\",\n",
+    "                                                 specification=heteroskedastic_specification,\n",
+    "                                                 model_type=\"Mixed Logit\",\n",
+    "                                                 names=heteroskedastic_names,\n",
+    "                                                 mixing_id_col=\"individual\",\n",
+    "                                                 mixing_vars=mixing_variables)\n",
+    "\n",
+    "# Create the initial values for the parameters\n",
+    "# being estimated. Note that we start at the MNL estimates\n",
+    "# and that we need to have initial variables for the\n",
+    "# standard deviation parameters that we'll estimate as well\n",
+    "# as for intercept for car (which we'll constrain to zero)\n",
+    "initial_values = np.concatenate((mnl_model.params.values[:3],\n",
+    "                                 np.zeros(1),  # for the car intercept\n",
+    "                                 mnl_model.params.values[3:],\n",
+    "                                 np.zeros(len(mixing_variables))))\n",
+    "\n",
+    "# Estimate the Mixed logit model.\n",
+    "# We set a seed for reproducibility, and we constrain the intercept\n",
+    "# for the car utility, i.e. position 4 (or in python, array index 3).\n",
+    "heteroskedastic_model_0.fit_mle(initial_values,\n",
+    "                                seed=26,\n",
+    "                                num_draws=500,\n",
+    "                                constrained_pos=[3])\n",
+    "\n",
+    "# View the estimation results\n",
+    "heteroskedastic_model_0.get_statsmodels_summary()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "From the estimation results above, we can see that $\\sigma_{\\textrm{bus}}$ is the smallest standard deviation. We will therefore constrain this $\\sigma_j$ to zero and re-estimate the model. Note also that the values of $\\sigma_j$ are reported as positive or negative. This is because PyLogit performed an unconstrained maximization, and the normal distribution is symmetric, so it doesn't matter if we show multiply by negative one or not."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "collapsed": false,
+    "scrolled": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Log-likelihood at zero: -291.1218\n",
+      "Initial Log-likelihood: -199.1284\n",
+      "Estimation Time: 4.72 seconds.\n",
+      "Final log-likelihood: -195.6216\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table class=\"simpletable\">\n",
+       "<caption>Mixed Logit Model Regression Results</caption>\n",
+       "<tr>\n",
+       "  <th>Dep. Variable:</th>      <td>choice</td>       <th>  No. Observations:  </th>    <td>210</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Model:</th>         <td>Mixed Logit Model</td> <th>  Df Residuals:      </th>    <td>199</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Method:</th>               <td>MLE</td>        <th>  Df Model:          </th>    <td>11</td>   \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Date:</th>          <td>Sat, 19 Nov 2016</td>  <th>  Pseudo R-squ.:     </th>   <td>0.328</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Time:</th>              <td>19:01:27</td>      <th>  Pseudo R-bar-squ.: </th>   <td>0.290</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>converged:</th>           <td>False</td>       <th>  Log-Likelihood:    </th> <td>-195.622</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th> </th>                      <td> </td>         <th>  LL-Null:           </th> <td>-291.122</td>\n",
+       "</tr>\n",
+       "</table>\n",
+       "<table class=\"simpletable\">\n",
+       "<tr>\n",
+       "                <td></td>                  <th>coef</th>     <th>std err</th>      <th>z</th>      <th>P>|z|</th> <th>[95.0% Conf. Int.]</th> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Air</th>                      <td>    4.6678</td> <td>    1.598</td> <td>    2.922</td> <td> 0.003</td> <td>    1.536     7.799</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Train</th>                    <td>    5.4416</td> <td>    1.180</td> <td>    4.612</td> <td> 0.000</td> <td>    3.129     7.754</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Bus</th>                      <td>    4.4082</td> <td>    1.121</td> <td>    3.931</td> <td> 0.000</td> <td>    2.210     6.606</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Car</th>                      <td>         0</td> <td>      nan</td> <td>      nan</td> <td>   nan</td> <td>      nan       nan</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Generalized Cost (all modes)</th> <td>   -0.0353</td> <td>    0.011</td> <td>   -3.168</td> <td> 0.002</td> <td>   -0.057    -0.013</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Terminal Time (all modes)</th>    <td>   -0.1184</td> <td>    0.021</td> <td>   -5.748</td> <td> 0.000</td> <td>   -0.159    -0.078</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Household Income (air mode)</th>  <td>    0.0415</td> <td>    0.027</td> <td>    1.527</td> <td> 0.127</td> <td>   -0.012     0.095</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Air</th>                <td>   -3.6390</td> <td>    1.099</td> <td>   -3.312</td> <td> 0.001</td> <td>   -5.793    -1.485</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Train</th>              <td>   -0.1010</td> <td>    3.871</td> <td>   -0.026</td> <td> 0.979</td> <td>   -7.688     7.486</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Bus</th>                <td>         0</td> <td>      nan</td> <td>      nan</td> <td>   nan</td> <td>      nan       nan</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Car</th>                <td>   -0.6942</td> <td>    1.569</td> <td>   -0.443</td> <td> 0.658</td> <td>   -3.769     2.380</td>\n",
+       "</tr>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "<class 'statsmodels.iolib.summary.Summary'>\n",
+       "\"\"\"\n",
+       "                     Mixed Logit Model Regression Results                     \n",
+       "==============================================================================\n",
+       "Dep. Variable:                 choice   No. Observations:                  210\n",
+       "Model:              Mixed Logit Model   Df Residuals:                      199\n",
+       "Method:                           MLE   Df Model:                           11\n",
+       "Date:                Sat, 19 Nov 2016   Pseudo R-squ.:                   0.328\n",
+       "Time:                        19:01:27   Pseudo R-bar-squ.:               0.290\n",
+       "converged:                      False   Log-Likelihood:               -195.622\n",
+       "                                        LL-Null:                      -291.122\n",
+       "================================================================================================\n",
+       "                                   coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
+       "------------------------------------------------------------------------------------------------\n",
+       "ASC Air                          4.6678      1.598      2.922      0.003         1.536     7.799\n",
+       "ASC Train                        5.4416      1.180      4.612      0.000         3.129     7.754\n",
+       "ASC Bus                          4.4082      1.121      3.931      0.000         2.210     6.606\n",
+       "ASC Car                               0        nan        nan        nan           nan       nan\n",
+       "Generalized Cost (all modes)    -0.0353      0.011     -3.168      0.002        -0.057    -0.013\n",
+       "Terminal Time (all modes)       -0.1184      0.021     -5.748      0.000        -0.159    -0.078\n",
+       "Household Income (air mode)      0.0415      0.027      1.527      0.127        -0.012     0.095\n",
+       "Sigma ASC Air                   -3.6390      1.099     -3.312      0.001        -5.793    -1.485\n",
+       "Sigma ASC Train                 -0.1010      3.871     -0.026      0.979        -7.688     7.486\n",
+       "Sigma ASC Bus                         0        nan        nan        nan           nan       nan\n",
+       "Sigma ASC Car                   -0.6942      1.569     -0.443      0.658        -3.769     2.380\n",
+       "================================================================================================\n",
+       "\"\"\""
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Initialize a new model\n",
+    "heteroskedastic_model_1 = pl.create_choice_model(data=mode_df,\n",
+    "                                                 alt_id_col=\"mode\",\n",
+    "                                                 obs_id_col=\"individual\",\n",
+    "                                                 choice_col=\"choice\",\n",
+    "                                                 specification=heteroskedastic_specification,\n",
+    "                                                 model_type=\"Mixed Logit\",\n",
+    "                                                 names=heteroskedastic_names,\n",
+    "                                                 mixing_id_col=\"individual\",\n",
+    "                                                 mixing_vars=mixing_variables)\n",
+    "\n",
+    "# Create the initial values for the parameters\n",
+    "# being estimated. Note that we start at the MNL estimates\n",
+    "# and that we need to have initial variables for the\n",
+    "# standard deviation parameters that we'll estimate as well\n",
+    "# as for intercept for car (which we'll constrain to zero)\n",
+    "initial_values = np.concatenate((mnl_model.params.values[:3],\n",
+    "                                 np.zeros(1),  # for the car intercept\n",
+    "                                 mnl_model.params.values[3:],\n",
+    "                                 np.zeros(len(mixing_variables))))\n",
+    "\n",
+    "# Estimate the Mixed logit model.\n",
+    "# We set a seed for reproducibility, and we constrain the parameter\n",
+    "# in position 4, i.e. the intercept for the car utility, and in\n",
+    "# position -2, i.e. the standard deviation for the bus.\n",
+    "heteroskedastic_model_1.fit_mle(initial_values,\n",
+    "                                seed=26,\n",
+    "                                num_draws=500,\n",
+    "                                constrained_pos=[3, -2])\n",
+    "\n",
+    "# View the estimation results\n",
+    "heteroskedastic_model_1.get_statsmodels_summary()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Given that the estimated $\\sigma_{\\textrm{train}}$ and $\\sigma_{\\textrm{car}}$ parameters are so close to zero and have such high p-values, we eliminate those variables only retain $\\sigma_{\\textrm{air}}$."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Log-likelihood at zero: -291.1218\n",
+      "Initial Log-likelihood: -195.8153\n",
+      "Estimation Time: 1.53 seconds.\n",
+      "Final log-likelihood: -195.6975\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table class=\"simpletable\">\n",
+       "<caption>Mixed Logit Model Regression Results</caption>\n",
+       "<tr>\n",
+       "  <th>Dep. Variable:</th>      <td>choice</td>       <th>  No. Observations:  </th>    <td>210</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Model:</th>         <td>Mixed Logit Model</td> <th>  Df Residuals:      </th>    <td>203</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Method:</th>               <td>MLE</td>        <th>  Df Model:          </th>     <td>7</td>   \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Date:</th>          <td>Sat, 19 Nov 2016</td>  <th>  Pseudo R-squ.:     </th>   <td>0.328</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Time:</th>              <td>19:01:28</td>      <th>  Pseudo R-bar-squ.: </th>   <td>0.304</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>converged:</th>           <td>True</td>        <th>  Log-Likelihood:    </th> <td>-195.697</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th> </th>                      <td> </td>         <th>  LL-Null:           </th> <td>-291.122</td>\n",
+       "</tr>\n",
+       "</table>\n",
+       "<table class=\"simpletable\">\n",
+       "<tr>\n",
+       "                <td></td>                  <th>coef</th>     <th>std err</th>      <th>z</th>      <th>P>|z|</th> <th>[95.0% Conf. Int.]</th> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Air</th>                      <td>    4.6406</td> <td>    1.255</td> <td>    3.698</td> <td> 0.000</td> <td>    2.181     7.100</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Train</th>                    <td>    5.1455</td> <td>    0.671</td> <td>    7.670</td> <td> 0.000</td> <td>    3.831     6.460</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Bus</th>                      <td>    4.1621</td> <td>    0.626</td> <td>    6.646</td> <td> 0.000</td> <td>    2.935     5.389</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Generalized Cost (all modes)</th> <td>   -0.0326</td> <td>    0.007</td> <td>   -4.698</td> <td> 0.000</td> <td>   -0.046    -0.019</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Terminal Time (all modes)</th>    <td>   -0.1142</td> <td>    0.012</td> <td>   -9.664</td> <td> 0.000</td> <td>   -0.137    -0.091</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Household Income (air mode)</th>  <td>    0.0372</td> <td>    0.025</td> <td>    1.508</td> <td> 0.132</td> <td>   -0.011     0.085</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Air</th>                <td>   -3.3096</td> <td>    0.841</td> <td>   -3.934</td> <td> 0.000</td> <td>   -4.959    -1.661</td>\n",
+       "</tr>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "<class 'statsmodels.iolib.summary.Summary'>\n",
+       "\"\"\"\n",
+       "                     Mixed Logit Model Regression Results                     \n",
+       "==============================================================================\n",
+       "Dep. Variable:                 choice   No. Observations:                  210\n",
+       "Model:              Mixed Logit Model   Df Residuals:                      203\n",
+       "Method:                           MLE   Df Model:                            7\n",
+       "Date:                Sat, 19 Nov 2016   Pseudo R-squ.:                   0.328\n",
+       "Time:                        19:01:28   Pseudo R-bar-squ.:               0.304\n",
+       "converged:                       True   Log-Likelihood:               -195.697\n",
+       "                                        LL-Null:                      -291.122\n",
+       "================================================================================================\n",
+       "                                   coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
+       "------------------------------------------------------------------------------------------------\n",
+       "ASC Air                          4.6406      1.255      3.698      0.000         2.181     7.100\n",
+       "ASC Train                        5.1455      0.671      7.670      0.000         3.831     6.460\n",
+       "ASC Bus                          4.1621      0.626      6.646      0.000         2.935     5.389\n",
+       "Generalized Cost (all modes)    -0.0326      0.007     -4.698      0.000        -0.046    -0.019\n",
+       "Terminal Time (all modes)       -0.1142      0.012     -9.664      0.000        -0.137    -0.091\n",
+       "Household Income (air mode)      0.0372      0.025      1.508      0.132        -0.011     0.085\n",
+       "Sigma ASC Air                   -3.3096      0.841     -3.934      0.000        -4.959    -1.661\n",
+       "================================================================================================\n",
+       "\"\"\""
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Initialize a new model. Note we use the original specification and\n",
+    "# original name dictionary because we are not estimating a Sigma ASC Car\n",
+    "# and those dictionaries already contain all the needed information to\n",
+    "# estimate Sigma ASC Air\n",
+    "heteroskedastic_model_2 = pl.create_choice_model(data=mode_df,\n",
+    "                                                 alt_id_col=\"mode\",\n",
+    "                                                 obs_id_col=\"individual\",\n",
+    "                                                 choice_col=\"choice\",\n",
+    "                                                 specification=specification_dict,\n",
+    "                                                 model_type=\"Mixed Logit\",\n",
+    "                                                 names=name_dict,\n",
+    "                                                 mixing_id_col=\"individual\",\n",
+    "                                                 mixing_vars=[\"ASC Air\"])\n",
+    "\n",
+    "# Create the initial values for the parameters\n",
+    "# being estimated. Note that we start at the estimates\n",
+    "# from the last model, using the estimated ASC's (minus the car ASC),\n",
+    "# the level-of-service coefficients, and Sigma Air.\n",
+    "initial_values = np.concatenate((heteroskedastic_model_1.params.values[:3],\n",
+    "                                 heteroskedastic_model_1.params.values[4:8]))\n",
+    "\n",
+    "# Estimate the Mixed logit model. The seed is for reproducibility\n",
+    "heteroskedastic_model_2.fit_mle(initial_values,\n",
+    "                                seed=26,\n",
+    "                                num_draws=500)\n",
+    "\n",
+    "# View the estimation results\n",
+    "heteroskedastic_model_2.get_statsmodels_summary()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Estimate a Mixed Logit Model with Nesting (i.e. correlated error terms)\n",
+    "In certain cases, one might wish to allow for correlated utilities. In particular, we use the $\\epsilon_{ij}$ terms to represent the unobserved factors that affect the utility gained by an individual $i$ if they choose alternative $j$. It may be quite reasonable to expect the unobserved factors that contribute to the utility of alternative $j$ (say the Train alternative) to be correlated with the unobserved factors that contribute to the utility of alternative $k$ (say the Bus alternative). For instance, we do not observe factors such as the access and egress time to the terminals for the train and bus modes. Given that these are ground transportation modes that require smaller terminals than airplanes, it is likely that the train and bus terminals are close to the center of downtown Sydney and downtown Melbourne, and thus likely to be closer to one's destination as opposed to the outskirts of the cities. Since these unobserved factors are likely to be correlated, the utilities of the two modes are likely to be correlated.\n",
+    "\n",
+    "One way to account for such correlation is through the addition of shared error components in one's utility equations. In our example specifically, we can add a error component to the train and bus utilities as follows:\n",
+    "<font size=4>$\\begin{align}\n",
+    "U_{ij} &= \\beta _{\\textrm{generalized_cost}} \\textrm{GC}_{ij} +\n",
+    "          \\beta _{\\textrm{terminal_time}} \\textrm{TTME}_{ij} +\n",
+    "          \\beta _{\\textrm{household_income}} d_{i,\\ j=\\textrm{air}} \\textrm{HINC}_{i} +\\\\\n",
+    "          &\\quad \\ \\sigma_{\\textrm{air}} d_{i,\\ j=\\textrm{air}} \\tilde{\\eta}_{ij} + \\sigma_{\\textrm{nest}} d_{i,\\ j \\in \\textrm{(train, bus)}} \\xi + \\epsilon_{ij}\\\\\n",
+    "\\textrm{where }& \\tilde{\\eta}_{ij} \\sim N\\left(\\alpha _{j}, 1\\right)\\\\\n",
+    "          &j \\in \\left\\lbrace \\textrm{air, train, bus, car}\\right\\rbrace\\\\\n",
+    "          &\\alpha _{\\textrm{car}} = 0 \\\\\n",
+    "          & \\xi \\sim N\\left( 0, 1 \\right)\n",
+    "\\end{align}\n",
+    "$</font><br>Note that we have removed the $\\sigma_j$ parameters for all $j \\neq \\textrm{air}$ because of the estimation results from above.<br>\n",
+    "\n",
+    "As before, we will need to implement this specification through a random-coefficients perspective, so we will add a dummy variable to the model that is $1$ if the alternative is train or bus, and $0$ otherwise. Then, when treating the coefficient on this dummy variable as a random coefficient, we will constrain the mean to be zero, and estimate the standard deviation. This is analagous to the way that we estimated the standard deviation for the car alternative, even though the \"ASC Car\" coefficient was constrained to be zero."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [],
+   "source": [
+    "# Add a \"nesting variable\" to the dataset by first\n",
+    "# initializing the variable for all modes, then\n",
+    "# setting the veriable equal to 1, only for the\n",
+    "# train (2) and bus(3) modes\n",
+    "mode_df[\"train_bus_nesting_dummy\"] = 0\n",
+    "mode_df.loc[mode_df[\"mode\"].isin([2, 3]),\n",
+    "            \"train_bus_nesting_dummy\"] = 1\n",
+    "\n",
+    "# Initialize the specification and name dictionaries\n",
+    "# for the model to be estimated.\n",
+    "nesting_specification = OrderedDict()\n",
+    "nesting_names = OrderedDict()\n",
+    "\n",
+    "# As with 'heteroskedastic model 2', we build off the\n",
+    "# original specification and name dictionaries because\n",
+    "# we are not estimating a value for Sigma ASC Car.\n",
+    "for key in specification_dict:\n",
+    "    nesting_specification[key] = specification_dict[key]\n",
+    "    nesting_names[key] = name_dict[key]\n",
+    "    \n",
+    "# Note that we are adding a single subset-specific coefficient to the\n",
+    "# nesting dummy. This coefficient (which will be constrained to zero), will\n",
+    "# be the mean of a randomly distributed nesting variable.\n",
+    "nesting_specification[\"train_bus_nesting_dummy\"] = [[2, 3]]\n",
+    "nesting_names[\"train_bus_nesting_dummy\"] = [\"Nesting Parameter\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Log-likelihood at zero: -291.1218\n",
+      "Initial Log-likelihood: -195.5820\n",
+      "Estimation Time: 1.38 seconds.\n",
+      "Final log-likelihood: -195.4987\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<table class=\"simpletable\">\n",
+       "<caption>Mixed Logit Model Regression Results</caption>\n",
+       "<tr>\n",
+       "  <th>Dep. Variable:</th>      <td>choice</td>       <th>  No. Observations:  </th>    <td>210</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Model:</th>         <td>Mixed Logit Model</td> <th>  Df Residuals:      </th>    <td>201</td>  \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Method:</th>               <td>MLE</td>        <th>  Df Model:          </th>     <td>9</td>   \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Date:</th>          <td>Sat, 19 Nov 2016</td>  <th>  Pseudo R-squ.:     </th>   <td>0.328</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Time:</th>              <td>19:01:30</td>      <th>  Pseudo R-bar-squ.: </th>   <td>0.298</td> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>converged:</th>           <td>True</td>        <th>  Log-Likelihood:    </th> <td>-195.499</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th> </th>                      <td> </td>         <th>  LL-Null:           </th> <td>-291.122</td>\n",
+       "</tr>\n",
+       "</table>\n",
+       "<table class=\"simpletable\">\n",
+       "<tr>\n",
+       "                <td></td>                  <th>coef</th>     <th>std err</th>      <th>z</th>      <th>P>|z|</th> <th>[95.0% Conf. Int.]</th> \n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Air</th>                      <td>    4.7379</td> <td>    1.422</td> <td>    3.333</td> <td> 0.001</td> <td>    1.952     7.524</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Train</th>                    <td>    5.2137</td> <td>    0.945</td> <td>    5.519</td> <td> 0.000</td> <td>    3.362     7.065</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>ASC Bus</th>                      <td>    4.2274</td> <td>    0.911</td> <td>    4.639</td> <td> 0.000</td> <td>    2.441     6.013</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Generalized Cost (all modes)</th> <td>   -0.0329</td> <td>    0.009</td> <td>   -3.463</td> <td> 0.001</td> <td>   -0.051    -0.014</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Terminal Time (all modes)</th>    <td>   -0.1157</td> <td>    0.018</td> <td>   -6.307</td> <td> 0.000</td> <td>   -0.152    -0.080</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Household Income (air mode)</th>  <td>    0.0358</td> <td>    0.025</td> <td>    1.411</td> <td> 0.158</td> <td>   -0.014     0.085</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Nesting Parameter</th>            <td>         0</td> <td>      nan</td> <td>      nan</td> <td>   nan</td> <td>      nan       nan</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma ASC Air</th>                <td>   -3.3560</td> <td>    1.016</td> <td>   -3.305</td> <td> 0.001</td> <td>   -5.346    -1.365</td>\n",
+       "</tr>\n",
+       "<tr>\n",
+       "  <th>Sigma Nesting Parameter</th>      <td>    0.4213</td> <td>    1.863</td> <td>    0.226</td> <td> 0.821</td> <td>   -3.230     4.072</td>\n",
+       "</tr>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "<class 'statsmodels.iolib.summary.Summary'>\n",
+       "\"\"\"\n",
+       "                     Mixed Logit Model Regression Results                     \n",
+       "==============================================================================\n",
+       "Dep. Variable:                 choice   No. Observations:                  210\n",
+       "Model:              Mixed Logit Model   Df Residuals:                      201\n",
+       "Method:                           MLE   Df Model:                            9\n",
+       "Date:                Sat, 19 Nov 2016   Pseudo R-squ.:                   0.328\n",
+       "Time:                        19:01:30   Pseudo R-bar-squ.:               0.298\n",
+       "converged:                       True   Log-Likelihood:               -195.499\n",
+       "                                        LL-Null:                      -291.122\n",
+       "================================================================================================\n",
+       "                                   coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
+       "------------------------------------------------------------------------------------------------\n",
+       "ASC Air                          4.7379      1.422      3.333      0.001         1.952     7.524\n",
+       "ASC Train                        5.2137      0.945      5.519      0.000         3.362     7.065\n",
+       "ASC Bus                          4.2274      0.911      4.639      0.000         2.441     6.013\n",
+       "Generalized Cost (all modes)    -0.0329      0.009     -3.463      0.001        -0.051    -0.014\n",
+       "Terminal Time (all modes)       -0.1157      0.018     -6.307      0.000        -0.152    -0.080\n",
+       "Household Income (air mode)      0.0358      0.025      1.411      0.158        -0.014     0.085\n",
+       "Nesting Parameter                     0        nan        nan        nan           nan       nan\n",
+       "Sigma ASC Air                   -3.3560      1.016     -3.305      0.001        -5.346    -1.365\n",
+       "Sigma Nesting Parameter          0.4213      1.863      0.226      0.821        -3.230     4.072\n",
+       "================================================================================================\n",
+       "\"\"\""
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Create a list of the variables whose standard deviations\n",
+    "# are to be estimated\n",
+    "mixing_vars_nesting = [\"ASC Air\", \"Nesting Parameter\"]\n",
+    "\n",
+    "nesting_model = pl.create_choice_model(data=mode_df,\n",
+    "                                       alt_id_col=\"mode\",\n",
+    "                                       obs_id_col=\"individual\",\n",
+    "                                       choice_col=\"choice\",\n",
+    "                                       specification=nesting_specification,\n",
+    "                                       model_type=\"Mixed Logit\",\n",
+    "                                       names=nesting_names,\n",
+    "                                       mixing_id_col=\"individual\",\n",
+    "                                       mixing_vars=mixing_vars_nesting)\n",
+    "\n",
+    "# Create the initial values for the parameters\n",
+    "# being estimated.\n",
+    "initial_values = np.concatenate((heteroskedastic_model_2.params.values[:6],\n",
+    "                                 np.zeros(1),  # for the nesting dummy\n",
+    "                                 heteroskedastic_model_2.params.values[-1:],\n",
+    "                                 np.zeros(1)))  # for the Sigma Nesting Dummy\n",
+    "\n",
+    "# Estimate the Mixed logit model.\n",
+    "# We set a seed for reproducibility, and we constrain the parameter\n",
+    "# in position 7, i.e. the nesting dummy.\n",
+    "nesting_model.fit_mle(initial_values,\n",
+    "                     seed=28,\n",
+    "                     num_draws=500,\n",
+    "                     constrained_pos=[6])\n",
+    "\n",
+    "# View the estimation results\n",
+    "nesting_model.get_statsmodels_summary()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "As the estimation results show, $\\sigma_{\\textrm{Nesting Parameter}}$ is not significantly different from zero at any common alpha-level. This indicates that the utilities of the train and bus coefficients may not actually be correlated, as we might have guessed a priori. This result could have been anticipated by considering the fact that this model is a restricted version of the \"Heteroskedastic Model 1\" that was estimated earlier. Here we are restricting $\\sigma_{\\textrm{train}}$ and $\\sigma_{\\textrm{bus}}$ terms to be the same value, and we are calling this value $\\sigma_{\\textrm{Nesting Parameter}}$. Given that neither parameter in the unrestricted model had a statistically significant difference from zero, we could anticipate that the restricted model would also not result in a parameter estimate that had a statistically significant difference from zero."
+   ]
+  }
+ ],
+ "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.12"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}

Added two new example notebooks. One for converting long-format dataframes to wide-format, and the other for estimating still more types of mixed logit models.