<NME> Asymmetric Choice Models Example.ipynb
<BEF> {
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# pyLogit Example\n",
    "The purpose of this notebook is to demonstrate they key functionalities of pyLogit:\n",
    "<ol>\n",
    "    <li> Estimating conditional logit-type models such as the four built-in asymmetric models.\n",
    "        <ol>\n",
    "            <li> Multinomial Asymmetric Logit Model</li>\n",
    "            <li> Multinomial Uneven Logit Model</li>\n",
    "            <li> Multinomial Scobit Model</li>\n",
    "            <li> Multinomial Clog-log Model</li>\n",
    "        </ol>\n",
    "    </li>\n",
    "</ol>\n",
    "\n",
    "For description and formulation of the aforementioned asymmetric choice models, see\n",
    "<blockquote>\n",
    "    Brathwaite, Timothy, and Joan Walker. \"Asymmetric, Closed-Form, Finite-Parameter Models of Multinomial Choice.\" arXiv preprint arXiv:1606.05900 (2016). http://arxiv.org/abs/1606.05900.\n",
    "</blockquote>\n",
    "The dataset being used for this example is the \"Swissmetro\" dataset used in the Python Biogeme examples. The data can be downloaded at <a href=\"http://biogeme.epfl.ch/examples_swissmetro.html\">http://biogeme.epfl.ch/examples_swissmetro.html</a>, and a detailed explanation of the variables and data-collection procedure can be found at http://www.strc.ch/conferences/2001/bierlaire1.pdf."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from collections import OrderedDict    # For recording the model specification \n",
    "\n",
    "import pandas as pd                    # For file input/output\n",
    "import numpy as np                     # For vectorized math operations\n",
    "\n",
    "import pylogit as pl                   # For MNL model estimation and\n",
    "                                       # conversion from wide to long format\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load the cleaned, long-format Swiss Metro data\n",
    "For details of how the dataset was cleaned and processed, see the \"Main PyLogit Example\" notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Load the dataset\n",
    "long_swiss_metro = pd.read_csv(\"../data/long_swiss_metro_data.csv\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "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>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>custom_id</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mode_id</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>3.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CHOICE</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>GROUP</th>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.00</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>SURVEY</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>SP</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ID</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>PURPOSE</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>FIRST</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TICKET</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>WHO</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LUGGAGE</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AGE</th>\n",
       "      <td>3.000000</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>3.00</td>\n",
       "      <td>3.000000</td>\n",
       "      <td>3.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MALE</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>INCOME</th>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.00</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>GA</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ORIGIN</th>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.00</td>\n",
       "      <td>2.000000</td>\n",
       "      <td>2.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>DEST</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>seat_configuration</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>travel_time</th>\n",
       "      <td>112.000000</td>\n",
       "      <td>63.000000</td>\n",
       "      <td>117.00</td>\n",
       "      <td>103.000000</td>\n",
       "      <td>60.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>headway</th>\n",
       "      <td>120.000000</td>\n",
       "      <td>20.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>30.000000</td>\n",
       "      <td>10.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>travel_cost</th>\n",
       "      <td>48.000000</td>\n",
       "      <td>52.000000</td>\n",
       "      <td>65.00</td>\n",
       "      <td>48.000000</td>\n",
       "      <td>49.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>travel_time_hrs</th>\n",
       "      <td>1.866667</td>\n",
       "      <td>1.050000</td>\n",
       "      <td>1.95</td>\n",
       "      <td>1.716667</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>headway_hrs</th>\n",
       "      <td>2.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.500000</td>\n",
       "      <td>0.166667</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>free_ticket</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>travel_cost_hundreth</th>\n",
       "      <td>0.480000</td>\n",
       "      <td>0.520000</td>\n",
       "      <td>0.65</td>\n",
       "      <td>0.480000</td>\n",
       "      <td>0.490000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>single_luggage_piece</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>multiple_luggage_pieces</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.00</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>regular_class</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>train_survey</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                  0          1       2           3          4\n",
       "custom_id                  1.000000   1.000000    1.00    2.000000   2.000000\n",
       "mode_id                    1.000000   2.000000    3.00    1.000000   2.000000\n",
       "CHOICE                     0.000000   1.000000    0.00    0.000000   1.000000\n",
       "GROUP                      2.000000   2.000000    2.00    2.000000   2.000000\n",
       "SURVEY                     0.000000   0.000000    0.00    0.000000   0.000000\n",
       "SP                         1.000000   1.000000    1.00    1.000000   1.000000\n",
       "ID                         1.000000   1.000000    1.00    1.000000   1.000000\n",
       "PURPOSE                    1.000000   1.000000    1.00    1.000000   1.000000\n",
       "FIRST                      0.000000   0.000000    0.00    0.000000   0.000000\n",
       "TICKET                     1.000000   1.000000    1.00    1.000000   1.000000\n",
       "WHO                        1.000000   1.000000    1.00    1.000000   1.000000\n",
       "LUGGAGE                    0.000000   0.000000    0.00    0.000000   0.000000\n",
       "AGE                        3.000000   3.000000    3.00    3.000000   3.000000\n",
       "MALE                       0.000000   0.000000    0.00    0.000000   0.000000\n",
       "INCOME                     2.000000   2.000000    2.00    2.000000   2.000000\n",
       "GA                         0.000000   0.000000    0.00    0.000000   0.000000\n",
       "ORIGIN                     2.000000   2.000000    2.00    2.000000   2.000000\n",
       "DEST                       1.000000   1.000000    1.00    1.000000   1.000000\n",
       "seat_configuration         0.000000   0.000000    0.00    0.000000   0.000000\n",
       "travel_time              112.000000  63.000000  117.00  103.000000  60.000000\n",
       "headway                  120.000000  20.000000    0.00   30.000000  10.000000\n",
       "travel_cost               48.000000  52.000000   65.00   48.000000  49.000000\n",
       "travel_time_hrs            1.866667   1.050000    1.95    1.716667   1.000000\n",
       "headway_hrs                2.000000   0.333333    0.00    0.500000   0.166667\n",
       "free_ticket                0.000000   0.000000    0.00    0.000000   0.000000\n",
       "travel_cost_hundreth       0.480000   0.520000    0.65    0.480000   0.490000\n",
       "single_luggage_piece       0.000000   0.000000    0.00    0.000000   0.000000\n",
       "multiple_luggage_pieces    0.000000   0.000000    0.00    0.000000   0.000000\n",
       "regular_class              1.000000   1.000000    1.00    1.000000   1.000000\n",
       "train_survey               1.000000   1.000000    1.00    1.000000   1.000000"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the first 5 rows of the data\n",
    "long_swiss_metro.head().T"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create the model specification\n",
    "The model specification being used in this example is the following:\n",
    "$$\n",
    "\\begin{aligned}\n",
    "V_{i, \\textrm{Train}} &= \\textrm{ASC Train} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{tt_transit} } \\textrm{Travel Time} _{ \\textrm{Train}} * \\frac{1}{60} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{tc_train} } \\textrm{Travel Cost}_{\\textrm{Train}} * \\left( GA == 0 \\right) * 0.01 + \\\\\n",
    "&\\quad \\beta _{ \\textrm{headway_train} } \\textrm{Headway} _{\\textrm{Train}} * \\frac{1}{60} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{survey} } \\left( \\textrm{Train Survey} == 1 \\right) \\\\\n",
    "\\\\\n",
    "V_{i, \\textrm{Swissmetro}} &= \\textrm{ASC Swissmetro} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{tt_transit} } \\textrm{Travel Time} _{ \\textrm{Swissmetro}} * \\frac{1}{60} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{tc_sm} } \\textrm{Travel Cost}_{\\textrm{Swissmetro}} * \\left( GA == 0 \\right) * 0.01 + \\\\\n",
    "&\\quad \\beta _{ \\textrm{headway_sm} } \\textrm{Heaway} _{\\textrm{Swissmetro}} * \\frac{1}{60} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{seat} } \\left( \\textrm{Seat Configuration} == 1 \\right) \\\\\n",
    "&\\quad \\beta _{ \\textrm{survey} } \\left( \\textrm{Train Survey} == 1 \\right) \\\\\n",
    "&\\quad \\beta _{ \\textrm{first_class} } \\left( \\textrm{First Class} == 0 \\right) \\\\\n",
    "\\\\\n",
    "V_{i, \\textrm{Car}} &= \\beta _{ \\textrm{tt_car} } \\textrm{Travel Time} _{ \\textrm{Car}} * \\frac{1}{60} + \\\\\n",
    "&\\quad \\beta _{ \\textrm{tc_car}} \\textrm{Travel Cost}_{\\textrm{Car}} * 0.01 + \\\\\n",
    "&\\quad \\beta _{\\textrm{luggage}=1} \\left( \\textrm{Luggage} == 1 \\right) + \\\\\n",
    "&\\quad \\beta _{\\textrm{luggage}>1} \\left( \\textrm{Luggage} > 1 \\right)\n",
    "\\end{aligned}\n",
    "$$\n",
    "\n",
    "Note that packages such as mlogit and statsmodels do not, by default, handle coefficients that vary over some alternatives but not all, e.g. the travel time coefficient that is specified as being the same for \"Train\" and \"Swissmetro\" but different for \"Car.\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# NOTE: - Specification and variable names must be ordered dictionaries.\n",
    "#       - Keys should be variables within the long format dataframe.\n",
    "#         The sole exception to this is the \"intercept\" key.\n",
    "#       - For the specification dictionary, the values should be lists\n",
    "#         of integers or or lists of lists of integers. Within a list, \n",
    "#         or within the inner-most list, the integers should be the \n",
    "#         alternative ID's of the alternative whose utility specification \n",
    "#         the explanatory variable is entering. Lists of lists denote \n",
    "#         alternatives that will share a common coefficient for the variable\n",
    "#         in question.\n",
    "\n",
    "basic_specification = OrderedDict()\n",
    "basic_names = OrderedDict()\n",
    "\n",
    "basic_specification[\"intercept\"] = [1, 2]\n",
    "basic_names[\"intercept\"] = ['ASC Train',\n",
    "                            'ASC Swissmetro']\n",
    "\n",
    "basic_specification[\"travel_time_hrs\"] = [[1, 2,], 3]\n",
    "basic_names[\"travel_time_hrs\"] = ['Travel Time, units:hrs (Train and Swissmetro)',\n",
    "                                  'Travel Time, units:hrs (Car)']\n",
    "\n",
    "basic_specification[\"travel_cost_hundreth\"] = [1, 2, 3]\n",
    "basic_names[\"travel_cost_hundreth\"] = ['Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)',\n",
    "                                       'Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)',\n",
    "                                       'Travel Cost, units: 0.01 CHF (Car)']\n",
    "\n",
    "basic_specification[\"headway_hrs\"] = [1, 2]\n",
    "basic_names[\"headway_hrs\"] = [\"Headway, units:hrs, (Train)\",\n",
    "                              \"Headway, units:hrs, (Swissmetro)\"]\n",
    "\n",
    "basic_specification[\"seat_configuration\"] = [2]\n",
    "basic_names[\"seat_configuration\"] = ['Airline Seat Configuration, base=No (Swissmetro)']\n",
    "\n",
    "basic_specification[\"train_survey\"] = [[1, 2]]\n",
    "basic_names[\"train_survey\"] = [\"Surveyed on a Train, base=No, (Train and Swissmetro)\"]\n",
    "\n",
    "basic_specification[\"regular_class\"] = [1]\n",
    "basic_names[\"regular_class\"] = [\"First Class == False, (Swissmetro)\"]\n",
    "\n",
    "basic_specification[\"single_luggage_piece\"] = [3]\n",
    "basic_names[\"single_luggage_piece\"] = [\"Number of Luggage Pieces == 1, (Car)\"]\n",
    "\n",
    "basic_specification[\"multiple_luggage_pieces\"] = [3]\n",
    "basic_names[\"multiple_luggage_pieces\"] = [\"Number of Luggage Pieces > 1, (Car)\"]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Estimate the conditional logit model, upon which the other models are based"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# The 'custom_alt_id' is the name of a column to be created in the long-format data\n",
    "# It will identify the alternative associated with each row.\n",
    "custom_alt_id = \"mode_id\"\n",
    "\n",
    "# Create a custom id column that ignores the fact that this is a \n",
    "# panel/repeated-observations dataset. Note the +1 ensures the id's start at one.\n",
    "obs_id_column = \"custom_id\"\n",
    "\n",
    "# Create a variable recording the choice column\n",
    "choice_column = \"CHOICE\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -6,964.6630\n",
      "Estimation Time: 0.12 seconds.\n",
      "Final log-likelihood: -5,159.2583\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>6,768</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Model:</th>         <td>Multinomial Logit Model</td> <th>  Df Residuals:      </th>    <td>6,754</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Method:</th>                  <td>MLE</td>           <th>  Df Model:          </th>     <td>14</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>             <td>Tue, 30 Aug 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.259</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                 <td>16:19:16</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.257</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>              <td>False</td>          <th>  Log-Likelihood:    </th> <td>-5,159.258</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                         <td> </td>            <th>  LL-Null:           </th> <td>-6,964.663</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 Train</th>                                                      <td>   -1.2929</td> <td>    0.146</td> <td>   -8.845</td> <td> 0.000</td> <td>   -1.579    -1.006</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Swissmetro</th>                                                 <td>   -0.5026</td> <td>    0.116</td> <td>   -4.332</td> <td> 0.000</td> <td>   -0.730    -0.275</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Train and Swissmetro)</th>                  <td>   -0.6990</td> <td>    0.042</td> <td>  -16.545</td> <td> 0.000</td> <td>   -0.782    -0.616</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Car)</th>                                   <td>   -0.7230</td> <td>    0.047</td> <td>  -15.340</td> <td> 0.000</td> <td>   -0.815    -0.631</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)</th>      <td>   -0.5618</td> <td>    0.094</td> <td>   -6.002</td> <td> 0.000</td> <td>   -0.745    -0.378</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)</th> <td>   -0.2817</td> <td>    0.045</td> <td>   -6.252</td> <td> 0.000</td> <td>   -0.370    -0.193</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost, units: 0.01 CHF (Car)</th>                             <td>   -0.5139</td> <td>    0.104</td> <td>   -4.953</td> <td> 0.000</td> <td>   -0.717    -0.311</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Train)</th>                                    <td>   -0.3143</td> <td>    0.062</td> <td>   -5.063</td> <td> 0.000</td> <td>   -0.436    -0.193</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Swissmetro)</th>                               <td>   -0.3773</td> <td>    0.196</td> <td>   -1.925</td> <td> 0.054</td> <td>   -0.761     0.007</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Airline Seat Configuration, base=No (Swissmetro)</th>               <td>   -0.7825</td> <td>    0.087</td> <td>   -8.970</td> <td> 0.000</td> <td>   -0.953    -0.611</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Surveyed on a Train, base=No, (Train and Swissmetro)</th>           <td>    2.5425</td> <td>    0.114</td> <td>   22.235</td> <td> 0.000</td> <td>    2.318     2.767</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>First Class == False, (Swissmetro)</th>                             <td>    0.5650</td> <td>    0.077</td> <td>    7.305</td> <td> 0.000</td> <td>    0.413     0.717</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces == 1, (Car)</th>                           <td>    0.4228</td> <td>    0.067</td> <td>    6.270</td> <td> 0.000</td> <td>    0.291     0.555</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces > 1, (Car)</th>                            <td>    1.4141</td> <td>    0.259</td> <td>    5.461</td> <td> 0.000</td> <td>    0.907     1.922</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:                6,768\n",
       "Model:             Multinomial Logit Model   Df Residuals:                    6,754\n",
       "Method:                                MLE   Df Model:                           14\n",
       "Date:                     Tue, 30 Aug 2016   Pseudo R-squ.:                   0.259\n",
       "Time:                             16:19:16   Pseudo R-bar-squ.:               0.257\n",
       "converged:                           False   Log-Likelihood:             -5,159.258\n",
       "                                             LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "                                                                     coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "----------------------------------------------------------------------------------------------------------------------------------\n",
       "ASC Train                                                         -1.2929      0.146     -8.845      0.000        -1.579    -1.006\n",
       "ASC Swissmetro                                                    -0.5026      0.116     -4.332      0.000        -0.730    -0.275\n",
       "Travel Time, units:hrs (Train and Swissmetro)                     -0.6990      0.042    -16.545      0.000        -0.782    -0.616\n",
       "Travel Time, units:hrs (Car)                                      -0.7230      0.047    -15.340      0.000        -0.815    -0.631\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)         -0.5618      0.094     -6.002      0.000        -0.745    -0.378\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)    -0.2817      0.045     -6.252      0.000        -0.370    -0.193\n",
       "Travel Cost, units: 0.01 CHF (Car)                                -0.5139      0.104     -4.953      0.000        -0.717    -0.311\n",
       "Headway, units:hrs, (Train)                                       -0.3143      0.062     -5.063      0.000        -0.436    -0.193\n",
       "Headway, units:hrs, (Swissmetro)                                  -0.3773      0.196     -1.925      0.054        -0.761     0.007\n",
       "Airline Seat Configuration, base=No (Swissmetro)                  -0.7825      0.087     -8.970      0.000        -0.953    -0.611\n",
       "Surveyed on a Train, base=No, (Train and Swissmetro)               2.5425      0.114     22.235      0.000         2.318     2.767\n",
       "First Class == False, (Swissmetro)                                 0.5650      0.077      7.305      0.000         0.413     0.717\n",
       "Number of Luggage Pieces == 1, (Car)                               0.4228      0.067      6.270      0.000         0.291     0.555\n",
       "Number of Luggage Pieces > 1, (Car)                                1.4141      0.259      5.461      0.000         0.907     1.922\n",
       "==================================================================================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Estimate the multinomial logit model (MNL)\n",
    "swissmetro_mnl = pl.create_choice_model(data=long_swiss_metro,\n",
    "                                        alt_id_col=custom_alt_id,\n",
    "                                        obs_id_col=obs_id_column,\n",
    "                                        choice_col=choice_column,\n",
    "                                        specification=basic_specification,\n",
    "                                        model_type=\"MNL\",\n",
    "                                        names=basic_names)\n",
    "\n",
    "# Specify the initial values and method for the optimization.\n",
    "swissmetro_mnl.fit_mle(np.zeros(14))\n",
    "\n",
    "# Look at the estimation results\n",
    "swissmetro_mnl.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test and demonstrate how to estimate different asymmetric, 'logit-type' models"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that in the models estimated below, we make use of PyLogit's ability to estimate \"outside\" intercept values. This means that while the index, $V_{ij} = X_{ij} \\beta$ (where $j$ is an alternative), will be subjected to some transformation, the intercept (i.e. the Alternative Specifc Constant) will not be subject to this transformation. This is done by removing the intercept from the specification dictionaries and by using the init_intercepts and init_coefs keyword argument in the fit_mle() function of the various choice models. See below for examples."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multinomial Asymmetric Logit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -5,159.2583\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"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Estimation Time: 0.47 seconds.\n",
      "Final log-likelihood: -4,990.9261\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table class=\"simpletable\">\n",
       "<caption>Multinomial Asymmetric Logit Model Regression Results</caption>\n",
       "<tr>\n",
       "  <th>Dep. Variable:</th>               <td>CHOICE</td>               <th>  No. Observations:  </th>    <td>6,768</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Model:</th>         <td>Multinomial Asymmetric Logit Model</td> <th>  Df Residuals:      </th>    <td>6,752</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Method:</th>                        <td>MLE</td>                <th>  Df Model:          </th>     <td>16</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>                   <td>Tue, 30 Aug 2016</td>          <th>  Pseudo R-squ.:     </th>    <td>0.283</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                       <td>16:19:41</td>              <th>  Pseudo R-bar-squ.: </th>    <td>0.281</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>                    <td>False</td>               <th>  Log-Likelihood:    </th> <td>-4,990.926</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                               <td> </td>                 <th>  LL-Null:           </th> <td>-6,964.663</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>shape_train</th>                                                    <td>    2.2006</td> <td>    1.207</td> <td>    1.824</td> <td> 0.068</td> <td>   -0.165     4.566</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>shape_swiss_metro</th>                                              <td>    2.8647</td> <td>    1.166</td> <td>    2.456</td> <td> 0.014</td> <td>    0.579     5.150</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Train</th>                                                      <td>   -5.0652</td> <td>    1.164</td> <td>   -4.350</td> <td> 0.000</td> <td>   -7.347    -2.783</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Swissmetro</th>                                                 <td>   -3.3396</td> <td>    1.150</td> <td>   -2.903</td> <td> 0.004</td> <td>   -5.594    -1.085</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Train and Swissmetro)</th>                  <td>   -0.2787</td> <td>    0.025</td> <td>  -11.040</td> <td> 0.000</td> <td>   -0.328    -0.229</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Car)</th>                                   <td>   -0.8638</td> <td>    0.081</td> <td>  -10.666</td> <td> 0.000</td> <td>   -1.022    -0.705</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)</th>      <td>   -0.3497</td> <td>    0.081</td> <td>   -4.297</td> <td> 0.000</td> <td>   -0.509    -0.190</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)</th> <td>   -0.1501</td> <td>    0.029</td> <td>   -5.149</td> <td> 0.000</td> <td>   -0.207    -0.093</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost, units: 0.01 CHF (Car)</th>                             <td>   -0.5074</td> <td>    0.142</td> <td>   -3.562</td> <td> 0.000</td> <td>   -0.787    -0.228</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Train)</th>                                    <td>   -0.3425</td> <td>    0.061</td> <td>   -5.614</td> <td> 0.000</td> <td>   -0.462    -0.223</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Swissmetro)</th>                               <td>   -0.0759</td> <td>    0.136</td> <td>   -0.559</td> <td> 0.576</td> <td>   -0.342     0.190</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Airline Seat Configuration, base=No (Swissmetro)</th>               <td>   -0.4591</td> <td>    0.197</td> <td>   -2.336</td> <td> 0.020</td> <td>   -0.844    -0.074</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Surveyed on a Train, base=No, (Train and Swissmetro)</th>           <td>    3.8486</td> <td>    0.210</td> <td>   18.320</td> <td> 0.000</td> <td>    3.437     4.260</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>First Class == False, (Swissmetro)</th>                             <td>    0.1400</td> <td>    0.076</td> <td>    1.833</td> <td> 0.067</td> <td>   -0.010     0.290</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces == 1, (Car)</th>                           <td>    0.6175</td> <td>    0.093</td> <td>    6.617</td> <td> 0.000</td> <td>    0.435     0.800</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces > 1, (Car)</th>                            <td>    1.5466</td> <td>    0.146</td> <td>   10.609</td> <td> 0.000</td> <td>    1.261     1.832</td>\n",
       "</tr>\n",
       "</table>"
      ],
      "text/plain": [
       "<class 'statsmodels.iolib.summary.Summary'>\n",
       "\"\"\"\n",
       "                    Multinomial Asymmetric Logit Model Regression Results                     \n",
       "==============================================================================================\n",
       "Dep. Variable:                                 CHOICE   No. Observations:                6,768\n",
       "Model:             Multinomial Asymmetric Logit Model   Df Residuals:                    6,752\n",
       "Method:                                           MLE   Df Model:                           16\n",
       "Date:                                Tue, 30 Aug 2016   Pseudo R-squ.:                   0.283\n",
       "Time:                                        16:19:41   Pseudo R-bar-squ.:               0.281\n",
       "converged:                                      False   Log-Likelihood:             -4,990.926\n",
       "                                                        LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "                                                                     coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "----------------------------------------------------------------------------------------------------------------------------------\n",
       "shape_train                                                        2.2006      1.207      1.824      0.068        -0.165     4.566\n",
       "shape_swiss_metro                                                  2.8647      1.166      2.456      0.014         0.579     5.150\n",
       "ASC Train                                                         -5.0652      1.164     -4.350      0.000        -7.347    -2.783\n",
       "ASC Swissmetro                                                    -3.3396      1.150     -2.903      0.004        -5.594    -1.085\n",
       "Travel Time, units:hrs (Train and Swissmetro)                     -0.2787      0.025    -11.040      0.000        -0.328    -0.229\n",
       "Travel Time, units:hrs (Car)                                      -0.8638      0.081    -10.666      0.000        -1.022    -0.705\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)         -0.3497      0.081     -4.297      0.000        -0.509    -0.190\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)    -0.1501      0.029     -5.149      0.000        -0.207    -0.093\n",
       "Travel Cost, units: 0.01 CHF (Car)                                -0.5074      0.142     -3.562      0.000        -0.787    -0.228\n",
       "Headway, units:hrs, (Train)                                       -0.3425      0.061     -5.614      0.000        -0.462    -0.223\n",
       "Headway, units:hrs, (Swissmetro)                                  -0.0759      0.136     -0.559      0.576        -0.342     0.190\n",
       "Airline Seat Configuration, base=No (Swissmetro)                  -0.4591      0.197     -2.336      0.020        -0.844    -0.074\n",
       "Surveyed on a Train, base=No, (Train and Swissmetro)               3.8486      0.210     18.320      0.000         3.437     4.260\n",
       "First Class == False, (Swissmetro)                                 0.1400      0.076      1.833      0.067        -0.010     0.290\n",
       "Number of Luggage Pieces == 1, (Car)                               0.6175      0.093      6.617      0.000         0.435     0.800\n",
       "Number of Luggage Pieces > 1, (Car)                                1.5466      0.146     10.609      0.000         1.261     1.832\n",
       "==================================================================================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create the various specification and name dictionaries \n",
    "# for the asymmetric logit model. It is the same as for the MNL\n",
    "# except that it excludes the intercept from V_{i, alternative}.\n",
    "asym_specification = OrderedDict()\n",
    "asym_names = OrderedDict()\n",
    "\n",
    "for col in basic_specification:\n",
    "    if col != \"intercept\":\n",
    "        asym_specification[col] = basic_specification[col]\n",
    "        asym_names[col] = basic_names[col]\n",
    "\n",
    "# Get the list of intercept names for the asymmetric logit model\n",
    "# This is used to tell PyLogit that we will be using 'outside'\n",
    "# intercept parameters.\n",
    "# See equation 2 of http://arxiv.org/abs/1606.05900 for more\n",
    "# details\n",
    "asym_intercept_names = basic_names[\"intercept\"]\n",
    "# Specify what alternative is not having its intercept estimated\n",
    "asym_intercept_ref_pos = 2\n",
    "\n",
    "# Give names to the shape parameters of the asymmetric logit model\n",
    "# Note that all of the shape parameters are not identifiable so we\n",
    "# need to restrict one of them. This accounts for why we do not have\n",
    "# a \"shape_car\" name.\n",
    "asym_shape_names = [\"shape_train\", \"shape_swiss_metro\"]\n",
    "\n",
    "# Note the index of the alternative whose shape parameter is constrained\n",
    "# (i.e. the Car alternative)\n",
    "asym_ref = 2\n",
    "\n",
    "swissmetro_asym = pl.create_choice_model(data=long_swiss_metro,\n",
    "                                         alt_id_col=custom_alt_id,\n",
    "                                         obs_id_col=obs_id_column,\n",
    "                                         choice_col=choice_column,\n",
    "                                         specification=asym_specification,\n",
    "                                         model_type=\"Asym\",\n",
    "                                         names=asym_names,\n",
    "                                         shape_names=asym_shape_names,\n",
    "                                         intercept_names=asym_intercept_names,\n",
    "                                         shape_ref_pos=asym_ref,\n",
    "                                         intercept_ref_pos=asym_intercept_ref_pos)\n",
    "\n",
    "# Also, note that we use None for initial values and use kwargs to\n",
    "# specify our initial values for the optimization. This is necessary\n",
    "# for the use of 'outside' intercept parameters.\n",
    "\n",
    "# Note that dividing the index coefficients by log(3) accounts for\n",
    "# the fact that when each shape parameter is 1/3, the value of the\n",
    "# asymmetric logit model's estimated index coefficients are equal to\n",
    "# the logit model's estimates, divided by log(3)\n",
    "\n",
    "swissmetro_asym.fit_mle(None,\n",
    "                        init_shapes=np.zeros(2),\n",
    "                        init_intercepts=swissmetro_mnl.params.values[:2],\n",
    "                        init_coefs=swissmetro_mnl.params.values[2:] / np.log(3),\n",
    "                        method=\"bfgs\")\n",
    "\n",
    "# Look at the model results\n",
    "swissmetro_asym.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multinomial Uneven Logit Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -6,175.2198\n",
      "Estimation Time: 0.93 seconds.\n",
      "Final log-likelihood: -4,954.6676\n"
     ]
    },
      "Estimation Time: 0.41 seconds.\n",
      "Final log-likelihood: -4,954.6676\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table class=\"simpletable\">\n",
       "<caption>Multinomial Uneven Logit Model Regression Results</caption>\n",
       "<tr>\n",
       "  <th>Dep. Variable:</th>             <td>CHOICE</td>             <th>  No. Observations:  </th>    <td>6,768</td>  \n",
       "</tr>\n",
       "  <th>Method:</th>                      <td>MLE</td>              <th>  Df Model:          </th>     <td>17</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>                 <td>Tue, 30 Aug 2016</td>        <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                     <td>16:20:35</td>            <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>                  <td>True</td>              <th>  Log-Likelihood:    </th> <td>-4,954.668</td>\n",
       "  <th>Time:</th>                     <td>14:29:17</td>            <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>                  <td>True</td>              <th>  Log-Likelihood:    </th> <td>-4,954.668</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                             <td> </td>               <th>  LL-Null:           </th> <td>-6,964.663</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>shape_train</th>                                                    <td>    0.9611</td> <td>    0.112</td> <td>    8.613</td> <td> 0.000</td> <td>    0.742     1.180</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>shape_swiss_metro</th>                                              <td>    0.1615</td> <td>    0.184</td> <td>    0.880</td> <td> 0.379</td> <td>   -0.198     0.521</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>shape_car</th>                                                      <td>   -0.2853</td> <td>    0.490</td> <td>   -0.582</td> <td> 0.561</td> <td>   -1.246     0.675</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Train</th>                                                      <td>   -1.0788</td> <td>    0.202</td> <td>   -5.351</td> <td> 0.000</td> <td>   -1.474    -0.684</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Swissmetro</th>                                                 <td>   -0.6369</td> <td>    0.201</td> <td>   -3.167</td> <td> 0.002</td> <td>   -1.031    -0.243</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Train and Swissmetro)</th>                  <td>   -0.3867</td> <td>    0.046</td> <td>   -8.424</td> <td> 0.000</td> <td>   -0.477    -0.297</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Car)</th>                                   <td>   -0.8798</td> <td>    0.470</td> <td>   -1.871</td> <td> 0.061</td> <td>   -1.801     0.042</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)</th>      <td>   -0.2607</td> <td>    0.061</td> <td>   -4.260</td> <td> 0.000</td> <td>   -0.381    -0.141</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)</th> <td>   -0.2098</td> <td>    0.048</td> <td>   -4.341</td> <td> 0.000</td> <td>   -0.304    -0.115</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost, units: 0.01 CHF (Car)</th>                             <td>   -0.5817</td> <td>    0.332</td> <td>   -1.750</td> <td> 0.080</td> <td>   -1.233     0.070</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Train)</th>                                    <td>   -0.2666</td> <td>    0.046</td> <td>   -5.750</td> <td> 0.000</td> <td>   -0.358    -0.176</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Swissmetro)</th>                               <td>   -0.3769</td> <td>    0.178</td> <td>   -2.120</td> <td> 0.034</td> <td>   -0.725    -0.029</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Airline Seat Configuration, base=No (Swissmetro)</th>               <td>   -0.1950</td> <td>    0.090</td> <td>   -2.171</td> <td> 0.030</td> <td>   -0.371    -0.019</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Surveyed on a Train, base=No, (Train and Swissmetro)</th>           <td>    2.1639</td> <td>    0.200</td> <td>   10.808</td> <td> 0.000</td> <td>    1.771     2.556</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>First Class == False, (Swissmetro)</th>                             <td>    0.1449</td> <td>    0.055</td> <td>    2.616</td> <td> 0.009</td> <td>    0.036     0.253</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces == 1, (Car)</th>                           <td>    0.6274</td> <td>    0.339</td> <td>    1.849</td> <td> 0.064</td> <td>   -0.038     1.292</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces > 1, (Car)</th>                            <td>    2.0020</td> <td>    0.831</td> <td>    2.409</td> <td> 0.016</td> <td>    0.373     3.631</td>\n",
       "</tr>\n",
       "</table>"
      ],
      "text/plain": [
       "Dep. Variable:                             CHOICE   No. Observations:                6,768\n",
       "Model:             Multinomial Uneven Logit Model   Df Residuals:                    6,751\n",
       "Method:                                       MLE   Df Model:                           17\n",
       "Date:                            Tue, 30 Aug 2016   Pseudo R-squ.:                   0.289\n",
       "Time:                                    16:20:35   Pseudo R-bar-squ.:               0.286\n",
       "converged:                                   True   Log-Likelihood:             -4,954.668\n",
       "                                                    LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "Time:                                    14:29:17   Pseudo R-bar-squ.:               0.286\n",
       "converged:                                   True   Log-Likelihood:             -4,954.668\n",
       "                                                    LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "                                                                     coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "----------------------------------------------------------------------------------------------------------------------------------\n",
       "shape_train                                                        0.9611      0.112      8.613      0.000         0.742     1.180\n",
       "shape_swiss_metro                                                  0.1615      0.184      0.880      0.379        -0.198     0.521\n",
       "shape_car                                                         -0.2853      0.490     -0.582      0.561        -1.246     0.675\n",
       "ASC Train                                                         -1.0788      0.202     -5.351      0.000        -1.474    -0.684\n",
       "ASC Swissmetro                                                    -0.6369      0.201     -3.167      0.002        -1.031    -0.243\n",
       "Travel Time, units:hrs (Train and Swissmetro)                     -0.3867      0.046     -8.424      0.000        -0.477    -0.297\n",
       "Travel Time, units:hrs (Car)                                      -0.8798      0.470     -1.871      0.061        -1.801     0.042\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)         -0.2607      0.061     -4.260      0.000        -0.381    -0.141\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)    -0.2098      0.048     -4.341      0.000        -0.304    -0.115\n",
       "Travel Cost, units: 0.01 CHF (Car)                                -0.5817      0.332     -1.750      0.080        -1.233     0.070\n",
       "Headway, units:hrs, (Train)                                       -0.2666      0.046     -5.750      0.000        -0.358    -0.176\n",
       "Headway, units:hrs, (Swissmetro)                                  -0.3769      0.178     -2.120      0.034        -0.725    -0.029\n",
       "Airline Seat Configuration, base=No (Swissmetro)                  -0.1950      0.090     -2.171      0.030        -0.371    -0.019\n",
       "Surveyed on a Train, base=No, (Train and Swissmetro)               2.1639      0.200     10.808      0.000         1.771     2.556\n",
       "First Class == False, (Swissmetro)                                 0.1449      0.055      2.616      0.009         0.036     0.253\n",
       "Number of Luggage Pieces == 1, (Car)                               0.6274      0.339      1.849      0.064        -0.038     1.292\n",
       "Number of Luggage Pieces > 1, (Car)                                2.0020      0.831      2.409      0.016         0.373     3.631\n",
       "==================================================================================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create the various specification and name dictionaries \n",
    "# for the uneven logit model. It is the same as for the MNL\n",
    "# except that it excludes the intercept from V_{i, alternative}.\n",
    "uneven_specification = OrderedDict()\n",
    "uneven_names = OrderedDict()\n",
    "\n",
    "for col in basic_specification:\n",
    "    if col != \"intercept\":\n",
    "        uneven_specification[col] = basic_specification[col]\n",
    "        uneven_names[col] = basic_names[col]\n",
    "\n",
    "# Get the list of intercept names for the uneven logit model\n",
    "# This is used to tell PyLogit that we will be using 'outside'\n",
    "# intercept parameters.\n",
    "# See equation 2 of http://arxiv.org/abs/1606.05900 for more\n",
    "# details\n",
    "uneven_intercept_names = basic_names[\"intercept\"]\n",
    "# Specify what alternative is not having its intercept estimated\n",
    "uneven_intercept_ref_pos = 2\n",
    "\n",
    "# Specify the names of the uneven logit model's shape parameters\n",
    "# Note that we include \"shape_car\" because all of the uneven logit\n",
    "# model's shape parameters are identifiable.\n",
    "uneven_shape_names = [\"shape_train\", \"shape_swiss_metro\", \"shape_car\"]\n",
    "\n",
    "swissmetro_uneven = pl.create_choice_model(data=long_swiss_metro,\n",
    "                                           alt_id_col=custom_alt_id,\n",
    "                                           obs_id_col=obs_id_column,\n",
    "                                           choice_col=choice_column,\n",
    "                                           specification=uneven_specification,\n",
    "# specify our initial values for the optimaztion. This is necessary\n",
    "# to use 'outside' intercept parameters with the model.\n",
    "swissmetro_uneven.fit_mle(None,\n",
    "                          init_shapes=np.ones(3),\n",
    "                          init_intercepts=swissmetro_mnl.params.values[:2],\n",
    "                          init_coefs=swissmetro_mnl.params.values[2:],\n",
    "                          method=\"bfgs\")\n",
    "# Also, note that we use None for initial values and use kwargs to\n",
    "# specify our initial values for the optimaztion. This is necessary\n",
    "# to use 'outside' intercept parameters with the model.\n",
    "swissmetro_uneven.fit_mle(None,\n",
    "                          init_shapes=np.zeros(3),\n",
    "                          init_intercepts=swissmetro_mnl.params.values[:2],\n",
    "                          init_coefs=swissmetro_mnl.params.values[2:],\n",
    "                          method=\"bfgs\")\n",
    "\n",
    "# Look at the model results\n",
    "swissmetro_uneven.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multinomial Scobit Model"
   ]
  },
  {
   "cell_type": "code",
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -5,159.2583\n",
      "Estimation Time: 0.52 seconds.\n",
      "Final log-likelihood: -4,952.9253\n"
     ]
    },
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -5,159.2583\n",
      "Estimation Time: 0.60 seconds.\n",
      "Final log-likelihood: -4,952.9253\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table class=\"simpletable\">\n",
       "  <th>Method:</th>                   <td>MLE</td>           <th>  Df Model:          </th>     <td>17</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>              <td>Tue, 30 Aug 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                  <td>16:21:26</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>               <td>False</td>          <th>  Log-Likelihood:    </th> <td>-4,952.925</td>\n",
       "<tr>\n",
       "  <th>Date:</th>              <td>Thu, 15 Sep 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                  <td>14:30:27</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>               <td>False</td>          <th>  Log-Likelihood:    </th> <td>-4,952.925</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                          <td> </td>            <th>  LL-Null:           </th> <td>-6,964.663</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>shape_train</th>                                                    <td>    0.8033</td> <td>    0.117</td> <td>    6.874</td> <td> 0.000</td> <td>    0.574     1.032</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>shape_swiss_metro</th>                                              <td>   -0.9112</td> <td>    0.489</td> <td>   -1.862</td> <td> 0.063</td> <td>   -1.871     0.048</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>shape_car</th>                                                      <td>   -1.4079</td> <td>    0.347</td> <td>   -4.052</td> <td> 0.000</td> <td>   -2.089    -0.727</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Train</th>                                                      <td>    1.0793</td> <td>    0.271</td> <td>    3.978</td> <td> 0.000</td> <td>    0.548     1.611</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Swissmetro</th>                                                 <td>   -0.7150</td> <td>    0.569</td> <td>   -1.257</td> <td> 0.209</td> <td>   -1.830     0.400</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Train and Swissmetro)</th>                  <td>   -0.5046</td> <td>    0.059</td> <td>   -8.493</td> <td> 0.000</td> <td>   -0.621    -0.388</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Car)</th>                                   <td>   -1.7342</td> <td>    0.510</td> <td>   -3.399</td> <td> 0.001</td> <td>   -2.734    -0.734</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)</th>      <td>   -0.3617</td> <td>    0.078</td> <td>   -4.624</td> <td> 0.000</td> <td>   -0.515    -0.208</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)</th> <td>   -0.3141</td> <td>    0.069</td> <td>   -4.542</td> <td> 0.000</td> <td>   -0.450    -0.179</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost, units: 0.01 CHF (Car)</th>                             <td>   -1.0225</td> <td>    0.380</td> <td>   -2.689</td> <td> 0.007</td> <td>   -1.768    -0.277</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Train)</th>                                    <td>   -0.2919</td> <td>    0.051</td> <td>   -5.703</td> <td> 0.000</td> <td>   -0.392    -0.192</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Swissmetro)</th>                               <td>   -0.3824</td> <td>    0.237</td> <td>   -1.611</td> <td> 0.107</td> <td>   -0.848     0.083</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Airline Seat Configuration, base=No (Swissmetro)</th>               <td>   -0.2021</td> <td>    0.095</td> <td>   -2.124</td> <td> 0.034</td> <td>   -0.389    -0.016</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Surveyed on a Train, base=No, (Train and Swissmetro)</th>           <td>    2.7869</td> <td>    0.206</td> <td>   13.526</td> <td> 0.000</td> <td>    2.383     3.191</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>First Class == False, (Swissmetro)</th>                             <td>    0.1346</td> <td>    0.064</td> <td>    2.117</td> <td> 0.034</td> <td>    0.010     0.259</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces == 1, (Car)</th>                           <td>    1.1631</td> <td>    0.327</td> <td>    3.555</td> <td> 0.000</td> <td>    0.522     1.804</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Number of Luggage Pieces > 1, (Car)</th>                            <td>    3.0167</td> <td>    0.627</td> <td>    4.808</td> <td> 0.000</td> <td>    1.787     4.246</td>\n",
       "Dep. Variable:                       CHOICE   No. Observations:                6,768\n",
       "Model:             Multinomial Scobit Model   Df Residuals:                    6,751\n",
       "Method:                                 MLE   Df Model:                           17\n",
       "Date:                      Tue, 30 Aug 2016   Pseudo R-squ.:                   0.289\n",
       "Time:                              16:21:26   Pseudo R-bar-squ.:               0.286\n",
       "converged:                            False   Log-Likelihood:             -4,952.925\n",
       "                                              LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "Dep. Variable:                       CHOICE   No. Observations:                6,768\n",
       "Model:             Multinomial Scobit Model   Df Residuals:                    6,751\n",
       "Method:                                 MLE   Df Model:                           17\n",
       "Date:                      Thu, 15 Sep 2016   Pseudo R-squ.:                   0.289\n",
       "Time:                              14:30:27   Pseudo R-bar-squ.:               0.286\n",
       "converged:                            False   Log-Likelihood:             -4,952.925\n",
       "                                              LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "                                                                     coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "----------------------------------------------------------------------------------------------------------------------------------\n",
       "shape_train                                                        0.8033      0.117      6.874      0.000         0.574     1.032\n",
       "shape_swiss_metro                                                 -0.9112      0.489     -1.862      0.063        -1.871     0.048\n",
       "shape_car                                                         -1.4079      0.347     -4.052      0.000        -2.089    -0.727\n",
       "ASC Train                                                          1.0793      0.271      3.978      0.000         0.548     1.611\n",
       "ASC Swissmetro                                                    -0.7150      0.569     -1.257      0.209        -1.830     0.400\n",
       "Travel Time, units:hrs (Train and Swissmetro)                     -0.5046      0.059     -8.493      0.000        -0.621    -0.388\n",
       "Travel Time, units:hrs (Car)                                      -1.7342      0.510     -3.399      0.001        -2.734    -0.734\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)         -0.3617      0.078     -4.624      0.000        -0.515    -0.208\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)    -0.3141      0.069     -4.542      0.000        -0.450    -0.179\n",
       "Travel Cost, units: 0.01 CHF (Car)                                -1.0225      0.380     -2.689      0.007        -1.768    -0.277\n",
       "Headway, units:hrs, (Train)                                       -0.2919      0.051     -5.703      0.000        -0.392    -0.192\n",
       "Headway, units:hrs, (Swissmetro)                                  -0.3824      0.237     -1.611      0.107        -0.848     0.083\n",
       "Airline Seat Configuration, base=No (Swissmetro)                  -0.2021      0.095     -2.124      0.034        -0.389    -0.016\n",
       "Surveyed on a Train, base=No, (Train and Swissmetro)               2.7869      0.206     13.526      0.000         2.383     3.191\n",
       "First Class == False, (Swissmetro)                                 0.1346      0.064      2.117      0.034         0.010     0.259\n",
       "Number of Luggage Pieces == 1, (Car)                               1.1631      0.327      3.555      0.000         0.522     1.804\n",
       "Number of Luggage Pieces > 1, (Car)                                3.0167      0.627      4.808      0.000         1.787     4.246\n",
       "==================================================================================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create the various specification and name dictionaries \n",
    "# for the scobit model. It is the same as for the MNL\n",
    "# except that it excludes the intercept from V_{i, alternative}.\n",
    "scobit_specification = OrderedDict()\n",
    "scobit_names = OrderedDict()\n",
    "\n",
    "for col in basic_specification:\n",
    "    if col != \"intercept\":\n",
    "        scobit_specification[col] = basic_specification[col]\n",
    "        scobit_names[col] = basic_names[col]\n",
    "\n",
    "# Get the list of intercept names for the scobit model\n",
    "# This is used to tell PyLogit that we will be using 'outside'\n",
    "# intercept parameters.\n",
    "# See equation 2 of http://arxiv.org/abs/1606.05900 for more\n",
    "# details\n",
    "scobit_intercept_names = basic_names[\"intercept\"]\n",
    "\n",
    "# Create the names of the shape parameters that are needed for the scobit model\n",
    "scobit_shape_names = [\"shape_train\", \"shape_swiss_metro\", \"shape_car\"]\n",
    "\n",
    "# Specify which intercept/ASC is not being estimated (namely, the Car intercept)\n",
    "scobit_intercept_ref = 2\n",
    "\n",
    "#Estimate the model\n",
    "swissmetro_scobit = pl.create_choice_model(data=long_swiss_metro,\n",
    "                                           alt_id_col=custom_alt_id,\n",
    "                                           obs_id_col=obs_id_column,\n",
    "                                           choice_col=choice_column,\n",
    "                                           specification=scobit_specification,\n",
    "                                           model_type=\"Scobit\",\n",
    "                                           names=scobit_names,\n",
    "                                           shape_names=scobit_shape_names,\n",
    "                                           intercept_ref_pos=scobit_intercept_ref,\n",
    "                                           intercept_names=scobit_intercept_names)\n",
    "\n",
    "# Note that we are using 'outside' intercept parameters for this model\n",
    "swissmetro_scobit.fit_mle(None,\n",
    "                          init_shapes=np.zeros(3),\n",
    "                          init_intercepts=swissmetro_mnl.params.values[:2],\n",
    "                          init_coefs=swissmetro_mnl.params.values[2:],\n",
    "                          method=\"BFGS\",\n",
    "                          maxiter=1200)\n",
    "\n",
    "# Look at the model results\n",
    "swissmetro_scobit.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Multinomial Clog-log Model"
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -6,055.5603\n",
      "Estimation Time: 0.57 seconds.\n",
      "Final log-likelihood: -5,191.9526\n"
     ]
    },
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -6,964.6630\n",
      "Initial Log-likelihood: -6,055.5603\n",
      "Estimation Time: 0.69 seconds.\n",
      "Final log-likelihood: -5,191.9526\n"
     ]
    },
       "  <th>Method:</th>                    <td>MLE</td>            <th>  Df Model:          </th>     <td>14</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>               <td>Tue, 30 Aug 2016</td>      <th>  Pseudo R-squ.:     </th>    <td>0.255</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                   <td>16:21:50</td>          <th>  Pseudo R-bar-squ.: </th>    <td>0.253</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>                <td>False</td>           <th>  Log-Likelihood:    </th> <td>-5,191.953</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Method:</th>                    <td>MLE</td>            <th>  Df Model:          </th>     <td>14</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>               <td>Thu, 15 Sep 2016</td>      <th>  Pseudo R-squ.:     </th>    <td>0.255</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                   <td>14:30:54</td>          <th>  Pseudo R-bar-squ.: </th>    <td>0.253</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>                <td>False</td>           <th>  Log-Likelihood:    </th> <td>-5,191.953</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                           <td> </td>             <th>  LL-Null:           </th> <td>-6,964.663</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 Train</th>                                                      <td>   -3.0252</td> <td>    0.137</td> <td>  -22.020</td> <td> 0.000</td> <td>   -3.294    -2.756</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC Swissmetro</th>                                                 <td>   -0.4904</td> <td>    0.123</td> <td>   -3.983</td> <td> 0.000</td> <td>   -0.732    -0.249</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Train and Swissmetro)</th>                  <td>   -0.1304</td> <td>    0.019</td> <td>   -6.866</td> <td> 0.000</td> <td>   -0.168    -0.093</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Time, units:hrs (Car)</th>                                   <td>   -0.4964</td> <td>    0.042</td> <td>  -11.889</td> <td> 0.000</td> <td>   -0.578    -0.415</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)</th>      <td>   -0.1982</td> <td>    0.041</td> <td>   -4.864</td> <td> 0.000</td> <td>   -0.278    -0.118</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)</th> <td>   -0.2011</td> <td>    0.033</td> <td>   -6.181</td> <td> 0.000</td> <td>   -0.265    -0.137</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Travel Cost, units: 0.01 CHF (Car)</th>                             <td>   -0.2982</td> <td>    0.088</td> <td>   -3.407</td> <td> 0.001</td> <td>   -0.470    -0.127</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Train)</th>                                    <td>    0.0198</td> <td>    0.017</td> <td>    1.140</td> <td> 0.254</td> <td>   -0.014     0.054</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Headway, units:hrs, (Swissmetro)</th>                               <td>   -1.0705</td> <td>    0.111</td> <td>   -9.658</td> <td> 0.000</td> <td>   -1.288    -0.853</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Airline Seat Configuration, base=No (Swissmetro)</th>               <td>   -0.2546</td> <td>    0.039</td> <td>   -6.527</td> <td> 0.000</td> <td>   -0.331    -0.178</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Surveyed on a Train, base=No, (Train and Swissmetro)</th>           <td>    1.4715</td> <td>    0.042</td> <td>   35.285</td> <td> 0.000</td> <td>    1.390     1.553</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>First Class == False, (Swissmetro)</th>                             <td>    0.2147</td> <td>    0.026</td> <td>    8.320</td> <td> 0.000</td> <td>    0.164     0.265</td>\n",
       "</tr>\n",
       "<tr>\n",
       "Dep. Variable:                         CHOICE   No. Observations:                6,768\n",
       "Model:             Multinomial Clog-log Model   Df Residuals:                    6,754\n",
       "Method:                                   MLE   Df Model:                           14\n",
       "Date:                        Tue, 30 Aug 2016   Pseudo R-squ.:                   0.255\n",
       "Time:                                16:21:50   Pseudo R-bar-squ.:               0.253\n",
       "converged:                              False   Log-Likelihood:             -5,191.953\n",
       "                                                LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "<class 'statsmodels.iolib.summary.Summary'>\n",
       "\"\"\"\n",
       "                    Multinomial Clog-log Model Regression Results                     \n",
       "======================================================================================\n",
       "Dep. Variable:                         CHOICE   No. Observations:                6,768\n",
       "Model:             Multinomial Clog-log Model   Df Residuals:                    6,754\n",
       "Method:                                   MLE   Df Model:                           14\n",
       "Date:                        Thu, 15 Sep 2016   Pseudo R-squ.:                   0.255\n",
       "Time:                                14:30:54   Pseudo R-bar-squ.:               0.253\n",
       "converged:                              False   Log-Likelihood:             -5,191.953\n",
       "                                                LL-Null:                    -6,964.663\n",
       "==================================================================================================================================\n",
       "                                                                     coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "----------------------------------------------------------------------------------------------------------------------------------\n",
       "ASC Train                                                         -3.0252      0.137    -22.020      0.000        -3.294    -2.756\n",
       "ASC Swissmetro                                                    -0.4904      0.123     -3.983      0.000        -0.732    -0.249\n",
       "Travel Time, units:hrs (Train and Swissmetro)                     -0.1304      0.019     -6.866      0.000        -0.168    -0.093\n",
       "Travel Time, units:hrs (Car)                                      -0.4964      0.042    -11.889      0.000        -0.578    -0.415\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Train)         -0.1982      0.041     -4.864      0.000        -0.278    -0.118\n",
       "Travel Cost * (Annual Pass == 0), units: 0.01 CHF (Swissmetro)    -0.2011      0.033     -6.181      0.000        -0.265    -0.137\n",
       "Travel Cost, units: 0.01 CHF (Car)                                -0.2982      0.088     -3.407      0.001        -0.470    -0.127\n",
       "Headway, units:hrs, (Train)                                        0.0198      0.017      1.140      0.254        -0.014     0.054\n",
       "Headway, units:hrs, (Swissmetro)                                  -1.0705      0.111     -9.658      0.000        -1.288    -0.853\n",
       "Airline Seat Configuration, base=No (Swissmetro)                  -0.2546      0.039     -6.527      0.000        -0.331    -0.178\n",
       "Surveyed on a Train, base=No, (Train and Swissmetro)               1.4715      0.042     35.285      0.000         1.390     1.553\n",
       "First Class == False, (Swissmetro)                                 0.2147      0.026      8.320      0.000         0.164     0.265\n",
       "Number of Luggage Pieces == 1, (Car)                               0.4234      0.055      7.717      0.000         0.316     0.531\n",
       "Number of Luggage Pieces > 1, (Car)                                1.1684      0.149      7.816      0.000         0.875     1.461\n",
       "==================================================================================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create the specification and name dictionaries \n",
    "# for the clog-log model.It is the same as for the MNL\n",
    "# except that it excludes the intercept from V_{i, alternative}.\n",
    "clog_specification = OrderedDict()\n",
    "clog_names = OrderedDict()\n",
    "\n",
    "# Copy the specification dictionary from the logit\n",
    "# model, without the intercept parameters so we\n",
    "# can place the intercept parameters outside the\n",
    "# index\n",
    "for col in basic_specification:\n",
    "    if col != \"intercept\":\n",
    "        clog_specification[col] = basic_specification[col]\n",
    "        clog_names[col] = basic_names[col]\n",
    "\n",
    "# Get the list of intercept names for the clog-log model\n",
    "# This is used to tell PyLogit that we will be using 'outside'\n",
    "# intercept parameters.\n",
    "# See equation 2 of http://arxiv.org/abs/1606.05900 for more\n",
    "# details\n",
    "clog_intercept_names = basic_names[\"intercept\"]\n",
    "\n",
    "# Specify which intercept/ASC is not being estimated \n",
    "# (i.e, the Car intercept)\n",
    "clog_intercept_ref = 2\n",
    "\n",
    "# Estimate the Clog-log model based on the MNL model\n",
    "# Note \"intercept_ref_pos=2\" means we are not estimating\n",
    "# an intercept for the alternative whose alternative id\n",
    "# falls at position 2 in the sorted array of alternative ids\n",
    "swissmetro_clog = pl.create_choice_model(data=long_swiss_metro,\n",
    "                                         alt_id_col=custom_alt_id,\n",
    "                                         obs_id_col=obs_id_column,\n",
    "                                         choice_col=choice_column,\n",
    "                                         specification=clog_specification,\n",
    "                                         model_type=\"Cloglog\",\n",
    "                                         intercept_ref_pos=clog_intercept_ref,\n",
    "                                         names=clog_names,\n",
    "                                         intercept_names=clog_intercept_names)\n",
    "\n",
    "# Estimate the clog log model. Note we don't pass one single array of\n",
    "# initial values but instead pass keyword arguments\n",
    "swissmetro_clog.fit_mle(None,\n",
    "                        init_intercepts=swissmetro_mnl.params.values[:2],\n",
    "                        init_coefs=swissmetro_mnl.params.values[2:],\n",
    "                        method='bfgs')\n",
    "\n",
    "# Look at the model results\n",
    "swissmetro_clog.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Look at the log-likelihood values overall and how they changed for the various models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Multinomial Logit Model              -5159.258305\n",
       "Multinomial Clog-log Model           -5191.952628\n",
       "Multinomial Asymmetric Logit Model   -4990.926075\n",
       "Multinomial Uneven Logit Model       -4954.667556\n",
       "Multinomial Scobit Model             -4952.925303\n",
       "Name: Log-likelihood Summary, dtype: float64"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a list of the estimated model objects\n",
    "model_objs = [swissmetro_mnl,\n",
    "              swissmetro_clog,\n",
    "              swissmetro_asym,\n",
    "              swissmetro_uneven,\n",
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python2"
  },
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As shown above, for this dataset, one can improve (in terms of log-likelihood) on the estimates offered by the standard logit model by switching to an asymmetric choice model. However, you may sometimes pay a computatiaonal price in terms of ease of estimation since these choice models have non-concave log-likelihood functions. Additionally, you may pay a price in terms of variance-inflation of one's estimates beacause the \"shape parameters\" are not locally orthogonal to the index coefficients. See \"Orthogonalizing Parametric Link Transformation Families in Binary Regression Analysis\" by Claudia Czado and Thomas J. Santner, The Canadian Journal of Statistics, Vol. 20, No. 1 (Mar., 1992), pp. 51-61, http://www.jstor.org/stable/3315574."
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "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": 0
}

<MSG> Updated asymmetric examples so that all models that nest the MNL model, start from the same initial values.

<DFF> @@ -499,7 +499,7 @@
      "text": [
       "Log-likelihood at zero: -6,964.6630\n",
       "Initial Log-likelihood: -6,964.6630\n",
-      "Estimation Time: 0.12 seconds.\n",
+      "Estimation Time: 0.14 seconds.\n",
       "Final log-likelihood: -5,159.2583\n"
      ]
     },
@@ -526,10 +526,10 @@
        "  <th>Method:</th>                  <td>MLE</td>           <th>  Df Model:          </th>     <td>14</td>    \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Date:</th>             <td>Tue, 30 Aug 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.259</td>  \n",
+       "  <th>Date:</th>             <td>Thu, 15 Sep 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.259</td>  \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Time:</th>                 <td>16:19:16</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.257</td>  \n",
+       "  <th>Time:</th>                 <td>14:27:59</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.257</td>  \n",
        "</tr>\n",
        "<tr>\n",
        "  <th>converged:</th>              <td>False</td>          <th>  Log-Likelihood:    </th> <td>-5,159.258</td>\n",
@@ -594,8 +594,8 @@
        "Dep. Variable:                      CHOICE   No. Observations:                6,768\n",
        "Model:             Multinomial Logit Model   Df Residuals:                    6,754\n",
        "Method:                                MLE   Df Model:                           14\n",
-       "Date:                     Tue, 30 Aug 2016   Pseudo R-squ.:                   0.259\n",
-       "Time:                             16:19:16   Pseudo R-bar-squ.:               0.257\n",
+       "Date:                     Thu, 15 Sep 2016   Pseudo R-squ.:                   0.259\n",
+       "Time:                             14:27:59   Pseudo R-bar-squ.:               0.257\n",
        "converged:                           False   Log-Likelihood:             -5,159.258\n",
        "                                             LL-Null:                    -6,964.663\n",
        "==================================================================================================================================\n",
@@ -689,7 +689,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Estimation Time: 0.47 seconds.\n",
+      "Estimation Time: 0.58 seconds.\n",
       "Final log-likelihood: -4,990.9261\n"
      ]
     },
@@ -708,10 +708,10 @@
        "  <th>Method:</th>                        <td>MLE</td>                <th>  Df Model:          </th>     <td>16</td>    \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Date:</th>                   <td>Tue, 30 Aug 2016</td>          <th>  Pseudo R-squ.:     </th>    <td>0.283</td>  \n",
+       "  <th>Date:</th>                   <td>Thu, 15 Sep 2016</td>          <th>  Pseudo R-squ.:     </th>    <td>0.283</td>  \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Time:</th>                       <td>16:19:41</td>              <th>  Pseudo R-bar-squ.: </th>    <td>0.281</td>  \n",
+       "  <th>Time:</th>                       <td>14:28:25</td>              <th>  Pseudo R-bar-squ.: </th>    <td>0.281</td>  \n",
        "</tr>\n",
        "<tr>\n",
        "  <th>converged:</th>                    <td>False</td>               <th>  Log-Likelihood:    </th> <td>-4,990.926</td>\n",
@@ -782,8 +782,8 @@
        "Dep. Variable:                                 CHOICE   No. Observations:                6,768\n",
        "Model:             Multinomial Asymmetric Logit Model   Df Residuals:                    6,752\n",
        "Method:                                           MLE   Df Model:                           16\n",
-       "Date:                                Tue, 30 Aug 2016   Pseudo R-squ.:                   0.283\n",
-       "Time:                                        16:19:41   Pseudo R-bar-squ.:               0.281\n",
+       "Date:                                Thu, 15 Sep 2016   Pseudo R-squ.:                   0.283\n",
+       "Time:                                        14:28:25   Pseudo R-bar-squ.:               0.281\n",
        "converged:                                      False   Log-Likelihood:             -4,990.926\n",
        "                                                        LL-Null:                    -6,964.663\n",
        "==================================================================================================================================\n",
@@ -891,8 +891,8 @@
      "output_type": "stream",
      "text": [
       "Log-likelihood at zero: -6,964.6630\n",
-      "Initial Log-likelihood: -6,175.2198\n",
-      "Estimation Time: 0.93 seconds.\n",
+      "Initial Log-likelihood: -5,159.2583\n",
+      "Estimation Time: 0.41 seconds.\n",
       "Final log-likelihood: -4,954.6676\n"
      ]
     },
@@ -911,10 +911,10 @@
        "  <th>Method:</th>                      <td>MLE</td>              <th>  Df Model:          </th>     <td>17</td>    \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Date:</th>                 <td>Tue, 30 Aug 2016</td>        <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
+       "  <th>Date:</th>                 <td>Thu, 15 Sep 2016</td>        <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Time:</th>                     <td>16:20:35</td>            <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
+       "  <th>Time:</th>                     <td>14:29:17</td>            <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
        "</tr>\n",
        "<tr>\n",
        "  <th>converged:</th>                  <td>True</td>              <th>  Log-Likelihood:    </th> <td>-4,954.668</td>\n",
@@ -988,8 +988,8 @@
        "Dep. Variable:                             CHOICE   No. Observations:                6,768\n",
        "Model:             Multinomial Uneven Logit Model   Df Residuals:                    6,751\n",
        "Method:                                       MLE   Df Model:                           17\n",
-       "Date:                            Tue, 30 Aug 2016   Pseudo R-squ.:                   0.289\n",
-       "Time:                                    16:20:35   Pseudo R-bar-squ.:               0.286\n",
+       "Date:                            Thu, 15 Sep 2016   Pseudo R-squ.:                   0.289\n",
+       "Time:                                    14:29:17   Pseudo R-bar-squ.:               0.286\n",
        "converged:                                   True   Log-Likelihood:             -4,954.668\n",
        "                                                    LL-Null:                    -6,964.663\n",
        "==================================================================================================================================\n",
@@ -1059,7 +1059,7 @@
     "# specify our initial values for the optimaztion. This is necessary\n",
     "# to use 'outside' intercept parameters with the model.\n",
     "swissmetro_uneven.fit_mle(None,\n",
-    "                          init_shapes=np.ones(3),\n",
+    "                          init_shapes=np.zeros(3),\n",
     "                          init_intercepts=swissmetro_mnl.params.values[:2],\n",
     "                          init_coefs=swissmetro_mnl.params.values[2:],\n",
     "                          method=\"bfgs\")\n",
@@ -1088,7 +1088,7 @@
      "text": [
       "Log-likelihood at zero: -6,964.6630\n",
       "Initial Log-likelihood: -5,159.2583\n",
-      "Estimation Time: 0.52 seconds.\n",
+      "Estimation Time: 0.60 seconds.\n",
       "Final log-likelihood: -4,952.9253\n"
      ]
     },
@@ -1107,10 +1107,10 @@
        "  <th>Method:</th>                   <td>MLE</td>           <th>  Df Model:          </th>     <td>17</td>    \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Date:</th>              <td>Tue, 30 Aug 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
+       "  <th>Date:</th>              <td>Thu, 15 Sep 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.289</td>  \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Time:</th>                  <td>16:21:26</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
+       "  <th>Time:</th>                  <td>14:30:27</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.286</td>  \n",
        "</tr>\n",
        "<tr>\n",
        "  <th>converged:</th>               <td>False</td>          <th>  Log-Likelihood:    </th> <td>-4,952.925</td>\n",
@@ -1184,8 +1184,8 @@
        "Dep. Variable:                       CHOICE   No. Observations:                6,768\n",
        "Model:             Multinomial Scobit Model   Df Residuals:                    6,751\n",
        "Method:                                 MLE   Df Model:                           17\n",
-       "Date:                      Tue, 30 Aug 2016   Pseudo R-squ.:                   0.289\n",
-       "Time:                              16:21:26   Pseudo R-bar-squ.:               0.286\n",
+       "Date:                      Thu, 15 Sep 2016   Pseudo R-squ.:                   0.289\n",
+       "Time:                              14:30:27   Pseudo R-bar-squ.:               0.286\n",
        "converged:                            False   Log-Likelihood:             -4,952.925\n",
        "                                              LL-Null:                    -6,964.663\n",
        "==================================================================================================================================\n",
@@ -1282,7 +1282,7 @@
      "text": [
       "Log-likelihood at zero: -6,964.6630\n",
       "Initial Log-likelihood: -6,055.5603\n",
-      "Estimation Time: 0.57 seconds.\n",
+      "Estimation Time: 0.69 seconds.\n",
       "Final log-likelihood: -5,191.9526\n"
      ]
     },
@@ -1301,10 +1301,10 @@
        "  <th>Method:</th>                    <td>MLE</td>            <th>  Df Model:          </th>     <td>14</td>    \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Date:</th>               <td>Tue, 30 Aug 2016</td>      <th>  Pseudo R-squ.:     </th>    <td>0.255</td>  \n",
+       "  <th>Date:</th>               <td>Thu, 15 Sep 2016</td>      <th>  Pseudo R-squ.:     </th>    <td>0.255</td>  \n",
        "</tr>\n",
        "<tr>\n",
-       "  <th>Time:</th>                   <td>16:21:50</td>          <th>  Pseudo R-bar-squ.: </th>    <td>0.253</td>  \n",
+       "  <th>Time:</th>                   <td>14:30:54</td>          <th>  Pseudo R-bar-squ.: </th>    <td>0.253</td>  \n",
        "</tr>\n",
        "<tr>\n",
        "  <th>converged:</th>                <td>False</td>           <th>  Log-Likelihood:    </th> <td>-5,191.953</td>\n",
@@ -1369,8 +1369,8 @@
        "Dep. Variable:                         CHOICE   No. Observations:                6,768\n",
        "Model:             Multinomial Clog-log Model   Df Residuals:                    6,754\n",
        "Method:                                   MLE   Df Model:                           14\n",
-       "Date:                        Tue, 30 Aug 2016   Pseudo R-squ.:                   0.255\n",
-       "Time:                                16:21:50   Pseudo R-bar-squ.:               0.253\n",
+       "Date:                        Thu, 15 Sep 2016   Pseudo R-squ.:                   0.255\n",
+       "Time:                                14:30:54   Pseudo R-bar-squ.:               0.253\n",
        "converged:                              False   Log-Likelihood:             -5,191.953\n",
        "                                                LL-Null:                    -6,964.663\n",
        "==================================================================================================================================\n",
@@ -1502,7 +1502,7 @@
  "metadata": {
   "anaconda-cloud": {},
   "kernelspec": {
-   "display_name": "Python [default]",
+   "display_name": "Python 2",
    "language": "python",
    "name": "python2"
   },

Updated asymmetric examples so that all models that nest the MNL model, start from the same initial values.