<NME> mlogit Benchmark--Train and Fishing-checkpoint.ipynb
<BEF> {
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mlogit Benchmark 1\n",
    "The purpose of this notebook is to:\n",
    "<ol>\n",
    "    <li> Demonstrate the use of the pyLogit to estimate conditional logit models.</li>\n",
    "    <li> Benchmark the results reported pyLogit against those reported by the mlogit package.</li>\n",
    "    <li> Demonstrate differences in model fit between the standard conditional logit model and the more general \"asymmetric choice models\" that can be estimated with pyLogit.</li>\n",
    "</ol>\n",
    "\n",
    "The models estimated in this notebook will be as follows:\n",
    "<ol>\n",
    "    <li> The \"Train\" model described on page 22 of the mlogit documentation. \n",
    "        <pre> ml.Train <- mlogit(choice ~ price + time + change + comfort | -1, Tr) </pre>\n",
    "    </li>\n",
    "    <li> The \"Fishing\" model described on pages 23-24 of the mlogit documentation\n",
    "        <pre> ml.Fish <- mlogit(mode ~ price | income | catch, Fishing, shape = \"wide\", varying = 2:9) </pre>\n",
    "    </li>\n",
    "</ol>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Import Needed libraries"
   ]
  },
  {
   "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\n",
    "                                       # To convert from wide to long format\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Load and look at the required datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Load the Train data, noting that the data is in wide data format\n",
    "wide_train_df = pd.read_csv(\"../data/train_data_r.csv\")\n",
    "\n",
    "# Load the Fishing data, noting that the data is in wide data format\n",
    "wide_fishing_df = pd.read_csv(\"../data/fishing_data_r.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>id</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>choiceid</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>4</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>choice</th>\n",
       "      <td>choice1</td>\n",
       "      <td>choice1</td>\n",
       "      <td>choice1</td>\n",
       "      <td>choice2</td>\n",
       "      <td>choice2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price1</th>\n",
       "      <td>2400</td>\n",
       "      <td>2400</td>\n",
       "      <td>2400</td>\n",
       "      <td>4000</td>\n",
       "      <td>2400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>time1</th>\n",
       "      <td>150</td>\n",
       "      <td>150</td>\n",
       "      <td>115</td>\n",
       "      <td>130</td>\n",
       "      <td>150</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>change1</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>comfort1</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price2</th>\n",
       "      <td>4000</td>\n",
       "      <td>3200</td>\n",
       "      <td>4000</td>\n",
       "      <td>3200</td>\n",
       "      <td>3200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>time2</th>\n",
       "      <td>150</td>\n",
       "      <td>130</td>\n",
       "      <td>115</td>\n",
       "      <td>150</td>\n",
       "      <td>150</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>change2</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>comfort2</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                0        1        2        3        4\n",
       "id              1        1        1        1        1\n",
       "choiceid        1        2        3        4        5\n",
       "choice    choice1  choice1  choice1  choice2  choice2\n",
       "price1       2400     2400     2400     4000     2400\n",
       "time1         150      150      115      130      150\n",
       "change1         0        0        0        0        0\n",
       "comfort1        1        1        1        1        1\n",
       "price2       4000     3200     4000     3200     3200\n",
       "time2         150      130      115      150      150\n",
       "change2         0        0        0        0        0\n",
       "comfort2        1        1        0        0        0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the raw Train data\n",
    "wide_train_df.head().T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "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>mode</th>\n",
       "      <td>charter</td>\n",
       "      <td>charter</td>\n",
       "      <td>boat</td>\n",
       "      <td>pier</td>\n",
       "      <td>boat</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price.beach</th>\n",
       "      <td>157.93</td>\n",
       "      <td>15.114</td>\n",
       "      <td>161.874</td>\n",
       "      <td>15.134</td>\n",
       "      <td>106.93</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price.pier</th>\n",
       "      <td>157.93</td>\n",
       "      <td>15.114</td>\n",
       "      <td>161.874</td>\n",
       "      <td>15.134</td>\n",
       "      <td>106.93</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price.boat</th>\n",
       "      <td>157.93</td>\n",
       "      <td>10.534</td>\n",
       "      <td>24.334</td>\n",
       "      <td>55.93</td>\n",
       "      <td>41.514</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price.charter</th>\n",
       "      <td>182.93</td>\n",
       "      <td>34.534</td>\n",
       "      <td>59.334</td>\n",
       "      <td>84.93</td>\n",
       "      <td>71.014</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>catch.beach</th>\n",
       "      <td>0.0678</td>\n",
       "      <td>0.1049</td>\n",
       "      <td>0.5333</td>\n",
       "      <td>0.0678</td>\n",
       "      <td>0.0678</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>catch.pier</th>\n",
       "      <td>0.0503</td>\n",
       "      <td>0.0451</td>\n",
       "      <td>0.4522</td>\n",
       "      <td>0.0789</td>\n",
       "      <td>0.0503</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>catch.boat</th>\n",
       "      <td>0.2601</td>\n",
       "      <td>0.1574</td>\n",
       "      <td>0.2413</td>\n",
       "      <td>0.1643</td>\n",
       "      <td>0.1082</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>catch.charter</th>\n",
       "      <td>0.5391</td>\n",
       "      <td>0.4671</td>\n",
       "      <td>1.0266</td>\n",
       "      <td>0.5391</td>\n",
       "      <td>0.324</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>income</th>\n",
       "      <td>7083.332</td>\n",
       "      <td>1250</td>\n",
       "      <td>3750</td>\n",
       "      <td>2083.333</td>\n",
       "      <td>4583.332</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      0        1        2         3         4\n",
       "mode            charter  charter     boat      pier      boat\n",
       "price.beach      157.93   15.114  161.874    15.134    106.93\n",
       "price.pier       157.93   15.114  161.874    15.134    106.93\n",
       "price.boat       157.93   10.534   24.334     55.93    41.514\n",
       "price.charter    182.93   34.534   59.334     84.93    71.014\n",
       "catch.beach      0.0678   0.1049   0.5333    0.0678    0.0678\n",
       "catch.pier       0.0503   0.0451   0.4522    0.0789    0.0503\n",
       "catch.boat       0.2601   0.1574   0.2413    0.1643    0.1082\n",
       "catch.charter    0.5391   0.4671   1.0266    0.5391     0.324\n",
       "income         7083.332     1250     3750  2083.333  4583.332"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the raw Fishing data\n",
    "wide_fishing_df.head().T"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Convert the wide format dataframes to long format"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3a. Perform needed data cleaning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recognizing that the Train dataset is a panel dataset, and recognizing that our estimated MNL model will not take the panel nature of the data into account, we need a new id column that specifies each individual choice situation.\n",
    "\n",
    "In a similar fashion, the Fishing data needs an observation id column, even though it is not a panel dataset. All datasets being used in pyLogit need an \"observation\" id column that denotes the id of what is being thought of as the unit of observation being modeled."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Note that we start the ids for the choice situations at 1.\n",
    "wide_train_df[\"choice_situation\"] = wide_train_df.index.values + 1\n",
    "\n",
    "wide_fishing_df[\"observation\"] = wide_fishing_df.index.values + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Noting that the columns denoting the choice for both the Train and the Fishing data are string objects, we need to convert the choice columns into integer based columns."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Convert the choice column for the Train data into integers\n",
    "# Note that we will use a 1 to denote 'choice1' and a 2 to \n",
    "# represent 'choice2'\n",
    "wide_train_df[\"choice\"] = wide_train_df[\"choice\"].map({'choice1': 1,\n",
    "                                                       'choice2': 2})\n",
    "\n",
    "# Convert the \"mode\" column for the Fishing data into an\n",
    "# integer based column. Use the following mapping:\n",
    "mode_name_to_id = dict(zip([\"beach\", \"pier\", \"boat\", \"charter\"],\n",
    "                           range(1, 5)))\n",
    "wide_fishing_df[\"mode\"] = wide_fishing_df[\"mode\"].map(mode_name_to_id)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For both the Train and the Fishing data, all of the alternatives are available in all choice situations. Note that, in general, this is not the case for choice data. As such we need to have columns that denote the availability of each alternative for each individual.\n",
    "\n",
    "These columns will all be filled with ones for each row in the wide format dataframes because all of the alternatives are always available for each individual."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Create the needed availability columns for the Train data\n",
    "# where each choice is a binary decision\n",
    "for i in [1, 2]:\n",
    "    wide_train_df[\"availability_{}\".format(i)] = 1\n",
    "    \n",
    "# Create the needed availability columns for the Fishing data\n",
    "# where each choice has four available alternatives\n",
    "for i in range(1, 5):\n",
    "    wide_fishing_df[\"availability_{}\".format(i)] = 1\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3b. Convert the Train dataset to long format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index([u'id', u'choiceid', u'choice', u'price1', u'time1', u'change1',\n",
       "       u'comfort1', u'price2', u'time2', u'change2', u'comfort2',\n",
       "       u'choice_situation', u'availability_1', u'availability_2'],\n",
       "      dtype='object')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the columns that we need to account for when converting from\n",
    "# the wide data format to the long data format.\n",
    "wide_train_df.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "##########\n",
    "# Define lists of the variables pertaining to each variable type\n",
    "# that we need to account for in the data format transformation\n",
    "##########\n",
    "# Determine the name for the alternative ids in the long format \n",
    "# data frame\n",
    "train_alt_id = \"alt_id\"\n",
    "# Determine the column that denotes the id of what we're treating\n",
    "# as individual observations, i.e. the choice situations.\n",
    "train_obs_id_col = \"choice_situation\"\n",
    "# Determine what column denotes the choice that was made\n",
    "train_choice_column = \"choice\"\n",
    "\n",
    "\n",
    "# Create the list of observation specific variables\n",
    "train_ind_variables = [\"id\", \"choiceid\"]\n",
    "\n",
    "# Specify the variables that vary across individuals and some or all alternatives\n",
    "# Note that each \"main\" key should be the desired name of the column in the long\n",
    "# data format. The inner keys shoud be the alternative ids that that have some\n",
    "# value for the \"main\" key variable.\n",
    "train_alt_varying_variables = {\"price\": {1: \"price1\",\n",
    "                                         2: \"price2\"},\n",
    "                               \"time\": {1: \"time1\",\n",
    "                                        2: \"time2\"},\n",
    "                               \"change\": {1: \"change1\",\n",
    "                                          2: \"change2\"},\n",
    "                               \"comfort\": {1: \"comfort1\",\n",
    "                                           2: \"comfort2\"}\n",
    "                               }\n",
    "\n",
    "# Specify the availability variables\n",
    "train_availability_variables = OrderedDict()\n",
    "for alt_id, var in zip([1, 2], [\"availability_1\", \"availability_2\"]):\n",
    "    train_availability_variables[alt_id] = var\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>choice_situation</th>\n",
       "      <th>alt_id</th>\n",
       "      <th>choice</th>\n",
       "      <th>id</th>\n",
       "      <th>choiceid</th>\n",
       "      <th>price</th>\n",
       "      <th>comfort</th>\n",
       "      <th>change</th>\n",
       "      <th>time</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>2400</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>150</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>4000</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>150</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>2400</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>150</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>3200</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>130</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>2400</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>115</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   choice_situation  alt_id  choice  id  choiceid  price  comfort  change  \\\n",
       "0                 1       1       1   1         1   2400        1       0   \n",
       "1                 1       2       0   1         1   4000        1       0   \n",
       "2                 2       1       1   1         2   2400        1       0   \n",
       "3                 2       2       0   1         2   3200        1       0   \n",
       "4                 3       1       1   1         3   2400        1       0   \n",
       "\n",
       "   time  \n",
       "0   150  \n",
       "1   150  \n",
       "2   150  \n",
       "3   130  \n",
       "4   115  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "##########\n",
    "# Actually perform the conversion to long format\n",
    "##########\n",
    "long_train_df = pl.convert_wide_to_long(wide_data=wide_train_df,\n",
    "                                        ind_vars=train_ind_variables,\n",
    "                                        alt_specific_vars=train_alt_varying_variables,\n",
    "                                        availability_vars=train_availability_variables,\n",
    "                                        obs_id_col=train_obs_id_col,\n",
    "                                        choice_col=train_choice_column,\n",
    "                                        new_alt_id_name=train_alt_id)\n",
    "\n",
    "# Look at the long format train data\n",
    "long_train_df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3c. Convert the Fishing data to long format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index([u'mode', u'price.beach', u'price.pier', u'price.boat', u'price.charter',\n",
       "       u'catch.beach', u'catch.pier', u'catch.boat', u'catch.charter',\n",
       "       u'income', u'observation', u'availability_1', u'availability_2',\n",
       "       u'availability_3', u'availability_4'],\n",
       "      dtype='object')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the columns that we need to account for when converting from\n",
    "# the wide data format to the long data format.\n",
    "wide_fishing_df.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "##########\n",
    "# Define lists of the variables pertaining to each variable type\n",
    "# that we need to account for in the data format transformation\n",
    "##########\n",
    "# Determine the name for the alternative ids in the long format \n",
    "# data frame\n",
    "fishing_alt_id = \"alt_id\"\n",
    "# Determine the column that denotes the id of what we're treating\n",
    "# as individual observations, i.e. the choice situations.\n",
    "fishing_obs_id_col = \"observation\"\n",
    "# Determine what column denotes the choice that was made\n",
    "fishing_choice_column = \"mode\"\n",
    "\n",
    "\n",
    "# Create the list of observation specific variables\n",
    "fishing_ind_variables = [\"income\"]\n",
    "\n",
    "# Specify the variables that vary across individuals and some or all alternatives\n",
    "# Note that each \"main\" key should be the desired name of the column in the long\n",
    "# data format. The inner keys shoud be the alternative ids that that have some\n",
    "# value for the \"main\" key variable.\n",
    "fishing_alt_varying_variables = {\"price\": {1: \"price.beach\",\n",
    "                                           2: \"price.pier\",\n",
    "                                           3: \"price.boat\",\n",
    "                                           4: \"price.charter\"},\n",
    "                                 \"catch\": {1: \"catch.beach\",\n",
    "                                           2: \"catch.pier\",\n",
    "                                           3: \"catch.boat\",\n",
    "                                           4: \"catch.charter\"},\n",
    "                                 }\n",
    "\n",
    "# Specify the availability variables\n",
    "fishing_availability_variables = OrderedDict()\n",
    "for alt_id, var in zip(range(1, 5), [\"availability_{}\".format(x) for x in range(1, 5)]):\n",
    "    fishing_availability_variables[alt_id] = var\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "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>observation</th>\n",
       "      <th>alt_id</th>\n",
       "      <th>mode</th>\n",
       "      <th>income</th>\n",
       "      <th>catch</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>7083.3317</td>\n",
       "      <td>0.0678</td>\n",
       "      <td>157.930</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>7083.3317</td>\n",
       "      <td>0.0503</td>\n",
       "      <td>157.930</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>7083.3317</td>\n",
       "      <td>0.2601</td>\n",
       "      <td>157.930</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>7083.3317</td>\n",
       "      <td>0.5391</td>\n",
       "      <td>182.930</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1249.9998</td>\n",
       "      <td>0.1049</td>\n",
       "      <td>15.114</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   observation  alt_id  mode     income   catch    price\n",
       "0            1       1     0  7083.3317  0.0678  157.930\n",
       "1            1       2     0  7083.3317  0.0503  157.930\n",
       "2            1       3     0  7083.3317  0.2601  157.930\n",
       "3            1       4     1  7083.3317  0.5391  182.930\n",
       "4            2       1     0  1249.9998  0.1049   15.114"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "##########\n",
    "# Actually perform the conversion to long format\n",
    "##########\n",
    "long_fishing_df = pl.convert_wide_to_long(wide_data=wide_fishing_df,\n",
    "                                          ind_vars=fishing_ind_variables,\n",
    "                                          alt_specific_vars=fishing_alt_varying_variables,\n",
    "                                          availability_vars=fishing_availability_variables,\n",
    "                                          obs_id_col=fishing_obs_id_col,\n",
    "                                          choice_col=fishing_choice_column,\n",
    "                                          new_alt_id_name=fishing_alt_id)\n",
    "\n",
    "# Look at the long format train data\n",
    "long_fishing_df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Create desired variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# For the Train data, scale the price and time variables so the units\n",
    "# are meaningful, namely hours and euros.\n",
    "long_train_df[\"price_euros\"] = long_train_df[\"price\"] / 100.0 * 2.20371\n",
    "long_train_df[\"time_hours\"] = long_train_df[\"time\"] / 60.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For numeric stability reasons, it is advised that one scale one's variables so that the estimated coefficients are similar in absolute magnitude, and if possible so that the estimated coefficients are close to 1 in absolute value (in other words, not terribly tiny or extremely large). This is done for the fishing data below"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Scale the income data\n",
    "long_fishing_df[\"income_thousandth\"] = long_fishing_df[\"income\"] / 1000.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Specify and estimate the desired models needed for benchmarking"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5a. Train Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that this dataset is a stated-preference dataset with unlabeled alternatives. Because the unobserved elements that affect a person's choice are assumed to be the same for both alternatives, the mean of the error terms is expected to be the same for the two alternatives, therefore the alternative specific constants (ASCs) would be the same and the difference between the two ASCs would be zero. Because of this, no ASCs are estimated for the Train model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index([u'choice_situation', u'alt_id', u'choice', u'id', u'choiceid', u'price',\n",
       "       u'comfort', u'change', u'time', u'price_euros', u'time_hours'],\n",
       "      dtype='object')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the columns available for use in specifying the model\n",
    "long_train_df.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Create the model specification\n",
    "train_spec = OrderedDict()\n",
    "train_names = OrderedDict()\n",
    "\n",
    "# Note that for the specification dictionary, the\n",
    "# keys should be the column names from the long format\n",
    "# dataframe and the values should be a list with a combination\n",
    "# of alternative id's and/or lists of alternative id's. There \n",
    "# should be one element for each beta that will be estimated \n",
    "# in relation to the given column. Lists of alternative id's\n",
    "# mean that all of the alternatives in the list will get a\n",
    "# single beta for them, for the given variable.\n",
    "# The names dictionary should contain one name for each\n",
    "# element (that is each alternative id or list of alternative \n",
    "# ids) in the specification dictionary value for the same \n",
    "# variable\n",
    "for col, display_name in [(\"price_euros\", \"price\"), \n",
    "                          (\"time_hours\", \"time\"), \n",
    "                          (\"change\", \"change\"), \n",
    "                          (\"comfort\", \"comfort\")]:\n",
    "    train_spec[col] = [[1, 2]]\n",
    "    train_names[col] = [display_name]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -2,030.2281\n",
      "Initial Log-likelihood: -2,030.2281\n",
      "Estimation Time: 0.02 seconds.\n",
      "Final log-likelihood: -1,724.1500\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>2,929</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Model:</th>         <td>Multinomial Logit Model</td> <th>  Df Residuals:      </th>    <td>2,925</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Method:</th>                  <td>MLE</td>           <th>  Df Model:          </th>      <td>4</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>             <td>Mon, 14 Mar 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.151</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                 <td>18:50:31</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.149</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>              <td>True</td>           <th>  Log-Likelihood:    </th> <td>-1,724.150</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                         <td> </td>            <th>  LL-Null:           </th> <td>-2,030.228</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>price</th>   <td>   -0.0674</td> <td>    0.003</td> <td>  -19.851</td> <td> 0.000</td> <td>   -0.074    -0.061</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>time</th>    <td>   -1.7206</td> <td>    0.160</td> <td>  -10.730</td> <td> 0.000</td> <td>   -2.035    -1.406</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>change</th>  <td>   -0.3263</td> <td>    0.059</td> <td>   -5.486</td> <td> 0.000</td> <td>   -0.443    -0.210</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>comfort</th> <td>   -0.9457</td> <td>    0.065</td> <td>  -14.562</td> <td> 0.000</td> <td>   -1.073    -0.818</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:                2,929\n",
       "Model:             Multinomial Logit Model   Df Residuals:                    2,925\n",
       "Method:                                MLE   Df Model:                            4\n",
       "Date:                     Mon, 14 Mar 2016   Pseudo R-squ.:                   0.151\n",
       "Time:                             18:50:31   Pseudo R-bar-squ.:               0.149\n",
       "converged:                            True   Log-Likelihood:             -1,724.150\n",
       "                                             LL-Null:                    -2,030.228\n",
       "==============================================================================\n",
       "                 coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "------------------------------------------------------------------------------\n",
       "price         -0.0674      0.003    -19.851      0.000        -0.074    -0.061\n",
       "time          -1.7206      0.160    -10.730      0.000        -2.035    -1.406\n",
       "change        -0.3263      0.059     -5.486      0.000        -0.443    -0.210\n",
       "comfort       -0.9457      0.065    -14.562      0.000        -1.073    -0.818\n",
       "==============================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create an instance of the MNL model class\n",
    "train_model = pl.create_choice_model(data=long_train_df,\n",
    "                                     alt_id_col=train_alt_id,\n",
    "                                     obs_id_col=train_obs_id_col,\n",
    "                                     choice_col=train_choice_column,\n",
    "                                     specification=train_spec,\n",
    "                                     model_type=\"MNL\",\n",
    "                                     names=train_names)\n",
    "\n",
    "# Estimate the given model, starting from a point of all zeros\n",
    "# as the initial values.\n",
    "train_model.fit_mle(np.zeros(4))\n",
    "\n",
    "# Look at the estimation summaries\n",
    "train_model.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Look at the corresponding results from mlogit:\n",
    "<pre>\n",
    "Call:\n",
    "mlogit(formula = choice ~ price + time + change + comfort | -1,\n",
    "    data = Tr, method = \"nr\", print.level = 0)\n",
    "Frequencies of alternatives: 12\n",
    "0.50324 0.49676\n",
    "nr method\n",
    "5 iterations, 0h:0m:0s\n",
    "g'(-H)^-1g = 0.00014\n",
    "successive fonction values within tolerance limits\n",
    "Coefficients :\n",
    "          Estimate Std. Error  t-value  Pr(>|t|)\n",
    "price   -0.0673580  0.0033933 -19.8506 < 2.2e-16 ***\n",
    "time    -1.7205514  0.1603517 -10.7299 < 2.2e-16 ***\n",
    "change  -0.3263409  0.0594892  -5.4857 4.118e-08 ***\n",
    "comfort -0.9457256  0.0649455 -14.5618 < 2.2e-16 ***\n",
    "---\n",
    "Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n",
    "Log-Likelihood: -1724.2\n",
    "</pre>\n",
    "\n",
    "In terms of differences between the estimation output of mlogit and my estimation output, the differencs seem mainly only be with the p-values. My p-values are calculated with respect to an asymptotic normal distribution whereas the p-values of mlogit are based on the t-distribution. This accounts for the p-value difference.\n",
    "\n",
    "There is a very slight difference between mlogits value for the time parameter and my own time parameter estimate, but this may simply be due to the convergance criteria that each of the packages are using."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5b. Fishing model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index([u'observation', u'alt_id', u'mode', u'income', u'catch', u'price',\n",
       "       u'income_thousandth'],\n",
       "      dtype='object')"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the columns available for use in specifying the model\n",
    "long_fishing_df.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Create the model specification\n",
    "fishing_spec = OrderedDict()\n",
    "fishing_names = OrderedDict()\n",
    "\n",
    "# Note that for the specification dictionary, the\n",
    "# keys should be the column names from the long format\n",
    "# dataframe and the values should be a list with a combination\n",
    "# of alternative id's and/or lists of alternative id's. There \n",
    "# should be one element for each beta that will be estimated \n",
    "# in relation to the given column. Lists of alternative id's\n",
    "# mean that all of the alternatives in the list will get a\n",
    "# single beta for them, for the given variable.\n",
    "# The names dictionary should contain one name for each\n",
    "# element (that is each alternative id or list of alternative \n",
    "# ids) in the specification dictionary value for the same \n",
    "# variable\n",
    "\n",
    "# Note the intercept for beach is constrained to zero for identification\n",
    "fishing_spec[\"intercept\"] = range(2, 5)\n",
    "fishing_names[\"intercept\"] = [\"ASC: pier\",\n",
    "                              \"ASC: boat\",\n",
    "                              \"ASC: charter\"]\n",
    "\n",
    "fishing_spec[\"price\"] = [[1, 2, 3, 4]]\n",
    "fishing_names[\"price\"] = [\"price\"]\n",
    "\n",
    "# Note the income coefficient for beach is constrained to zero for identification\n",
    "# Note also that we use the scaled variables because they numerically perform better\n",
    "\n",
    "# fishing_spec[\"income\"] = range(2, 5)\n",
    "# fishing_names[\"income\"] = [\"income_{}\".format(x) \n",
    "#                            for x in [\"pier\", \"boat\", \"charter\"]]\n",
    "\n",
    "fishing_spec[\"income_thousandth\"] = range(2, 5)\n",
    "fishing_names[\"income_thousandth\"] = [\"income_{} / 1000\".format(x) \n",
    "                                      for x in [\"pier\", \"boat\", \"charter\"]]\n",
    "\n",
    "fishing_spec[\"catch\"] = range(1, 5)\n",
    "fishing_names[\"catch\"] = [\"catch_{}\".format(x) for x in\n",
    "                          [\"beach\", \"pier\", \"boat\", \"charter\"]]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Log-likelihood at zero: -1,638.5999\n",
      "Initial Log-likelihood: -1,638.5999\n",
      "Estimation Time: 0.02 seconds.\n",
      "Final log-likelihood: -1,199.1434\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table class=\"simpletable\">\n",
       "<caption>Multinomial Logit Model Regression Results</caption>\n",
       "<tr>\n",
       "  <th>Dep. Variable:</th>          <td>mode</td>           <th>  No. Observations:  </th>    <td>1,182</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Model:</th>         <td>Multinomial Logit Model</td> <th>  Df Residuals:      </th>    <td>1,171</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Method:</th>                  <td>MLE</td>           <th>  Df Model:          </th>     <td>11</td>    \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Date:</th>             <td>Mon, 14 Mar 2016</td>     <th>  Pseudo R-squ.:     </th>    <td>0.268</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>Time:</th>                 <td>18:50:31</td>         <th>  Pseudo R-bar-squ.: </th>    <td>0.261</td>  \n",
       "</tr>\n",
       "<tr>\n",
       "  <th>converged:</th>              <td>False</td>          <th>  Log-Likelihood:    </th> <td>-1,199.143</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th> </th>                         <td> </td>            <th>  LL-Null:           </th> <td>-1,638.600</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: pier</th>             <td>    1.0430</td> <td>    0.295</td> <td>    3.531</td> <td> 0.000</td> <td>    0.464     1.622</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC: boat</th>             <td>    0.8418</td> <td>    0.300</td> <td>    2.807</td> <td> 0.005</td> <td>    0.254     1.430</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>ASC: charter</th>          <td>    2.1549</td> <td>    0.297</td> <td>    7.244</td> <td> 0.000</td> <td>    1.572     2.738</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>price</th>                 <td>   -0.0253</td> <td>    0.002</td> <td>  -14.405</td> <td> 0.000</td> <td>   -0.029    -0.022</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>income_pier / 1000</th>    <td>   -0.1355</td> <td>    0.051</td> <td>   -2.648</td> <td> 0.008</td> <td>   -0.236    -0.035</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>income_boat / 1000</th>    <td>    0.0554</td> <td>    0.052</td> <td>    1.063</td> <td> 0.288</td> <td>   -0.047     0.158</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>income_charter / 1000</th> <td>   -0.0723</td> <td>    0.053</td> <td>   -1.376</td> <td> 0.169</td> <td>   -0.175     0.031</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>catch_beach</th>           <td>    3.1177</td> <td>    0.713</td> <td>    4.372</td> <td> 0.000</td> <td>    1.720     4.515</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>catch_pier</th>            <td>    2.8512</td> <td>    0.775</td> <td>    3.681</td> <td> 0.000</td> <td>    1.333     4.369</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>catch_boat</th>            <td>    2.5425</td> <td>    0.523</td> <td>    4.864</td> <td> 0.000</td> <td>    1.518     3.567</td>\n",
       "</tr>\n",
       "<tr>\n",
       "  <th>catch_charter</th>         <td>    0.7595</td> <td>    0.154</td> <td>    4.925</td> <td> 0.000</td> <td>    0.457     1.062</td>\n",
       "</tr>\n",
       "</table>"
      ],
      "text/plain": [
       "<class 'statsmodels.iolib.summary.Summary'>\n",
       "\"\"\"\n",
       "                     Multinomial Logit Model Regression Results                    \n",
       "===================================================================================\n",
       "Dep. Variable:                        mode   No. Observations:                1,182\n",
       "Model:             Multinomial Logit Model   Df Residuals:                    1,171\n",
       "Method:                                MLE   Df Model:                           11\n",
       "Date:                     Mon, 14 Mar 2016   Pseudo R-squ.:                   0.268\n",
       "Time:                             18:50:31   Pseudo R-bar-squ.:               0.261\n",
       "converged:                           False   Log-Likelihood:             -1,199.143\n",
       "                                             LL-Null:                    -1,638.600\n",
       "=========================================================================================\n",
       "                            coef    std err          z      P>|z|      [95.0% Conf. Int.]\n",
       "-----------------------------------------------------------------------------------------\n",
       "ASC: pier                 1.0430      0.295      3.531      0.000         0.464     1.622\n",
       "ASC: boat                 0.8418      0.300      2.807      0.005         0.254     1.430\n",
       "ASC: charter              2.1549      0.297      7.244      0.000         1.572     2.738\n",
       "price                    -0.0253      0.002    -14.405      0.000        -0.029    -0.022\n",
       "income_pier / 1000       -0.1355      0.051     -2.648      0.008        -0.236    -0.035\n",
       "income_boat / 1000        0.0554      0.052      1.063      0.288        -0.047     0.158\n",
       "income_charter / 1000    -0.0723      0.053     -1.376      0.169        -0.175     0.031\n",
       "catch_beach               3.1177      0.713      4.372      0.000         1.720     4.515\n",
       "catch_pier                2.8512      0.775      3.681      0.000         1.333     4.369\n",
       "catch_boat                2.5425      0.523      4.864      0.000         1.518     3.567\n",
       "catch_charter             0.7595      0.154      4.925      0.000         0.457     1.062\n",
       "=========================================================================================\n",
       "\"\"\""
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create an instance of the MNL model class\n",
    "fishing_model = pl.create_choice_model(data=long_fishing_df,\n",
    "                                       alt_id_col=fishing_alt_id,\n",
    "                                       obs_id_col=fishing_obs_id_col,\n",
    "                                       choice_col=fishing_choice_column,\n",
    "                                       specification=fishing_spec,\n",
    "                                       model_type=\"MNL\",\n",
    "                                       names=fishing_names)\n",
    "\n",
    "# Estimate the given model, starting from a point of all zeros\n",
    "# as the initial values.\n",
    "fishing_model.fit_mle(np.zeros(11))\n",
    "\n",
    "# Look at the estimation summaries\n",
    "fishing_model.get_statsmodels_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Look at the results from mlogit:\n",
    "<pre>\n",
    "Call:\n",
    "mlogit(formula = mode ~ price | income | catch, data = Fishing, \n",
    "    shape = \"wide\", varying = 2:9, method = \"nr\", print.level = 0)\n",
    "\n",
    "Frequencies of alternatives:\n",
    "  beach    boat charter    pier \n",
    "0.11337 0.35364 0.38240 0.15059 \n",
    "\n",
    "nr method\n",
    "7 iterations, 0h:0m:0s \n",
    "g'(-H)^-1g = 2.54E-05 \n",
    "successive function values within tolerance limits \n",
    "\n",
    "Coefficients :\n",
    "                       Estimate  Std. Error  t-value  Pr(>|t|)    \n",
    "boat:(intercept)     8.4184e-01  2.9996e-01   2.8065 0.0050080 ** \n",
    "charter:(intercept)  2.1549e+00  2.9746e-01   7.2443 4.348e-13 ***\n",
    "pier:(intercept)     1.0430e+00  2.9535e-01   3.5315 0.0004132 ***\n",
    "price               -2.5281e-02  1.7551e-03 -14.4046 < 2.2e-16 ***\n",
    "boat:income          5.5428e-05  5.2130e-05   1.0633 0.2876612    \n",
    "charter:income      -7.2337e-05  5.2557e-05  -1.3764 0.1687088    \n",
    "pier:income         -1.3550e-04  5.1172e-05  -2.6480 0.0080977 ** \n",
    "beach:catch          3.1177e+00  7.1305e-01   4.3724 1.229e-05 ***\n",
    "boat:catch           2.5425e+00  5.2274e-01   4.8638 1.152e-06 ***\n",
    "charter:catch        7.5949e-01  1.5420e-01   4.9254 8.417e-07 ***\n",
    "pier:catch           2.8512e+00  7.7464e-01   3.6807 0.0002326 ***\n",
    "---\n",
    "Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1\n",
    "\n",
    "Log-Likelihood: -1199.1\n",
    "McFadden R^2:  0.19936 \n",
    "Likelihood ratio test : chisq = 597.16 (p.value = < 2.22e-16)\n",
    "</pre>\n",
    "\n",
    "The coefficient estimates, std. error, and t-values are exactly equal. The p-value differences are, as already noted, because mlogit uses the t-distribution whereas pyLogit uses an asymptotic normal distribution. The log-likelihoods of our final model is also the same.\n",
    "\n",
    "Note that the McFadden R^2 values are different. I am not sure how the mlogit value is calculated. From \"Coefficients of Determination for Multiple Logistic Regression Analysis\" by Scott Menard (2000), The American Statistician, 54:1, 17-24, we have the following equation:\n",
    "<center>\n",
    "$\\textrm{McFadden's R^2} = 1 - \\frac{\\mathscr{L}_M}{\\mathscr{L}_0}$\n",
    "</center>\n",
    "which evaluates to 0.2681902 not 0.19936. This is provided that my null-log-likelihood is correct. The next cell shows this to be the case and verifies pyLogit's calculated McFadden's R^2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pyLogit's null log-likelihood is correct: True\n",
      "McFadden's R^2 is 0.26819\n"
     ]
    }
   ],
   "source": [
    "##########\n",
    "# Make sure that pyLogit's null log-likelihood \n",
    "# and McFadden's R^2 are correct\n",
    "##########\n",
    "# Note that every observation in the Fishing dataset\n",
    "# has 4 available alternatives, therefore the null \n",
    "# probability is 0.25\n",
    "null_prob = 0.25\n",
    "\n",
    "# Calculate how many observations are in the Fishing \n",
    "# dataset\n",
    "num_fishing_obs = wide_fishing_df.shape[0]\n",
    "\n",
    "# Calculate the Fishing dataset's null log-likelihood \n",
    "null_fishing_log_likelihood = (num_fishing_obs * \n",
    "                               np.log(null_prob))\n",
    "\n",
    "# Determine whether pyLogit's null log-likelihood is correct\n",
    "correct_null_ll = (null_fishing_log_likelihood == \n",
    "                   fishing_model.null_log_likelihood)\n",
    "print \"pyLogit's null log-likelihood is correct:\", correct_null_ll\n",
    "\n",
    "# Calculate McFadden's R^2\n",
    "mcfaddens_r2 = 1 - (fishing_model.log_likelihood / fishing_model.null_log_likelihood)\n",
    "print \"McFadden's R^2 is {:.5f}\".format(mcfaddens_r2)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}

<MSG> Fixed Typos

<DFF> @@ -9,7 +9,6 @@
     "<ol>\n",
     "    <li> Demonstrate the use of the pyLogit to estimate conditional logit models.</li>\n",
     "    <li> Benchmark the results reported pyLogit against those reported by the mlogit package.</li>\n",
-    "    <li> Demonstrate differences in model fit between the standard conditional logit model and the more general \"asymmetric choice models\" that can be estimated with pyLogit.</li>\n",
     "</ol>\n",
     "\n",
     "The models estimated in this notebook will be as follows:\n",

Fixed Typos