# Alternative Specific Variables in R

I am building a discrete choice model (rail and auto). I have the cost of a trip for each mode (rail versus auto). The utility equations I am building are denoted below: \begin{align*} V_\text{auto} &= \beta_1\cdot\mbox{IVTT}_\text{auto}+ \beta_2\cdot\mbox{OVTT}_\text{auto} \\ V_\text{rail} &= \beta_0+ \beta_1 \cdot\mbox{IVTT}_\text{rail} + \beta_2 \cdot\mbox{OVTT}_\text{rail}+ \beta_3×\mbox{Cost}_\text{rail} \end{align*} The code I have is:

data_mlogit<-mlogit.data(newdata,shape="wide",choice="choice",
alt.levels=c("auto","rail"),varying=c(6:8,10:12))
model <- mlogit(choice ~ ivtt+ovtt+cost|0|0, data_mlogit)


How can I make the code understand to use the cost rail variable only without using the cost auto variable? I don't want the cost variable (auto) to be part of the utility equation for the auto mode.

• Try setting all auto cost values to NA. Aug 6, 2014 at 19:15
• This might cause difficulties if the OP wanted to use the auto cost variable later. Is there a formula-oriented approach? Aug 6, 2014 at 20:07

## 1 Answer

I will treat this answer in two parts:

# Why would you want to do this?

To begin with, variables like cost and travel time vary across alternatives, which actually makes them generic variables. The multinomial logit model is defined on the difference between two utility functions. Say you have two alternatives (1 and 2), where $x$ is the same in both. If you difference the utility equations, $\alpha_1 + \beta x - [\alpha_2 + \beta x]$ will cancel out $\beta$. So you estimate them as alternative-specific parameters $\alpha_1 + \beta_1 x - [\alpha_2 + \beta_2 x]$, allowing them to be defined.

But if $x_1$ and $x_2$ are different, the equation is identifiable with a single $\beta$, $\alpha_1 + \beta x_1 - [\alpha_2 + \beta x_2]$

If you estimate this model (I'm only going to use one travel time)

$$U_{train} = \alpha_{train} + \beta_{tt} (TT_{train})$$ $$U_{auto} = \alpha_{auto} + \beta_{tt} (TT_{auto})$$

You estimate three parameters ($\alpha_{train}, \alpha_{auto}, \beta_{tt}$). If you insist on estimating alternative-specific parameters for $\beta_{tt:auto}, \beta_{tt:train}$, you have spent a degree of freedom estimating a parameter that you don't actually need, which makes your model less efficient, with knock-on consequences for your hypothesis tests. Not to mention that cross-elasticities are lots easier to calculate with generic coefficients...

You only need alternative specific coefficients if you have variables that don't vary across alternatives, like if you had income, or the distance between the start and end of the trip.

# Okay, you want to do this anyways, so how do you do it?

There are a couple of ways that I might do this. First I'm going to build a simple dataset from the Biogeme swissmetro dataset.

library(foreign)
swissmetro <- read.delim("~/Downloads/swissmetro.dat")

library(dplyr)
swissmetro <- swissmetro %>%
filter(CHOICE %in% c(1, 3)) %>%
mutate(choice = factor(CHOICE, labels = c("train", "car")),
tt.train = TRAIN_TT, tt.car = CAR_TT,
cost.train = TRAIN_CO, cost.car = CAR_CO) %>%
select(ID, choice, tt.train, tt.car, cost.train, cost.car)

library(mlogit)
sm <- reshape(swissmetro, varying = 3:6, direction = "long")
sm <- sm %>%
mutate(choice = ifelse(choice == time, TRUE, FALSE), alt = time) %>%
arrange(id) %>% select(-time)
sm.mlogit <- mlogit.data(sm, choice = "choice", id.var = "ID", alt.var = "alt",
shape = "long")

head(sm.mlogit)
##         ID choice  tt cost id   alt
## 1.train  1   TRUE 103   36  1 train
## 1.car    1  FALSE  90   65  1   car
## 2.train  7   TRUE  80   42  2 train
## 2.car    7  FALSE  72  140  2   car
## 3.train  8  FALSE 100   22  3 train
## 3.car    8   TRUE  80   24  3   car


This replicates (what I think is) your data pretty well, though with only one travel time variable. We can and should treat both tt and cost as generic, giving us the most efficient model,

mnl1 <- mlogit(choice ~ tt + cost, data = sm.mlogit)
summary(mnl1)

##
## Call:
## mlogit(formula = choice ~ tt + cost, data = sm.mlogit, method = "nr",
##     print.level = 0)
##
## Frequencies of alternatives:
##   car train
## 0.684 0.316
##
## nr method
## 6 iterations, 0h:0m:0s
## g'(-H)^-1g = 2.11E-05
## successive function values within tolerance limits
##
## Coefficients :
##                    Estimate Std. Error t-value Pr(>|t|)
## train:(intercept) -1.33e+00   4.56e-02  -29.16   <2e-16 ***
## tt                -2.57e-04   4.69e-04   -0.55     0.58
## cost               1.40e-03   5.92e-05   23.71   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Log-Likelihood: -2180
## McFadden R^2:  0.225
## Likelihood ratio test : chisq = 1260 (p.value = <2e-16)


## Attempt 1: intercept interaction

My first idea is to interact the generic variables with an intercept, which is the same as forcing your missing $\beta_{train}$ to equal $0$.

sm.mlogit$car <- ifelse(sm.mlogit$alt == "train", 0, 1)
head(sm.mlogit)

##         ID choice  tt cost id   alt car
## 1.train  1   TRUE 103   36  1 train   0
## 1.car    1  FALSE  90   65  1   car   1
## 2.train  7   TRUE  80   42  2 train   0
## 2.car    7  FALSE  72  140  2   car   1
## 3.train  8  FALSE 100   22  3 train   0
## 3.car    8   TRUE  80   24  3   car   1

mnl2 <- mlogit(choice ~ tt + I(cost*car), data = sm.mlogit)
summary(mnl2)

##
## Call:
## mlogit(formula = choice ~ tt + I(cost * car), data = sm.mlogit,
##     method = "nr", print.level = 0)
##
## Frequencies of alternatives:
##   car train
## 0.684 0.316
##
## nr method
## 6 iterations, 0h:0m:0s
## g'(-H)^-1g = 1.29E-06
## successive function values within tolerance limits
##
## Coefficients :
##                   Estimate Std. Error t-value Pr(>|t|)
## train:(intercept) 1.01e+00   7.58e-02   13.30   <2e-16 ***
## tt                7.21e-05   4.72e-04    0.15     0.88
## I(cost * car)     2.84e-02   1.04e-03   27.42   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Log-Likelihood: -2230
## McFadden R^2:  0.205
## Likelihood ratio test : chisq = 1150 (p.value = <2e-16)

• @Feras, you may have a perfectly valid reason to do this. If you do, can you share it with me? Aug 7, 2014 at 1:35