I am generating data from the following synthetic mixed effects model for the utility of agent $h$ choosing transportation mode $j$:
$U_{hj} = \beta_{\text{price}} X_{h,\text{price}_j} + \beta_{\text{time}} X_{h,\text{time}_j} + \gamma_h X_{h,\text{bus}_j}+ \epsilon_{hj} \\ \gamma_h \sim \text{N}(0, 10)$
where $X_{h,\text{price}_j},X_{h,\text{time}_j}$ are agent $h$'s price and time for transporation mode $j$. $X_{h,\text{bus}_j}$ is an indicator function which is equal to 1 if mode $j$ is a bus.
The true model has $\beta_{\text{price}} = \beta_{\text{time}} = -1$.
For each agent, I generate the price and time covariates ($X_{h,\text{price}_j},X_{h,\text{time}_j}$) for each mode of transportation (red bus, train, car) and I sample the random effect $\gamma_h$ for each agent from $N(0,10)$, and then sample the transportation choice from the corresponding logit model.
Here's the R code that generates the choice data:
library(mlogit)
set.seed(1987)
n.samples <- 10000
re.sd <- 10 # random effect standard deviation
## generate price, time covariates
mode <- c('red.bus', 'train', 'car')
is.bus <- c(1, 0, 0)
price.data <- rnorm(3*n.samples) + c(2,5,10)
time.data <- rnorm(3*n.samples) + c(10, 5, 2)
obs <- data.frame(mode=mode,
price=price.data,
time=time.data,
bus=is.bus)
## generate random effect + choice data
obs$agent.id <- rep(1:n.samples, each=3)
obs$choice <- NA
obs$util <- NA
for( a.id in unique(obs$agent.id) ) {
xx.sub <- obs[obs$agent.id == a.id,]
obs$util[obs$agent.id == a.id] <- xx.sub$price*-1 + xx.sub$time*-1 + xx.sub$bus*rnorm(1,sd=re.sd)
uu <- obs$util[obs$agent.id == a.id]
p.vec <- exp(uu)/sum(exp(uu))
obs$choice[obs$agent.id == a.id] <- rmultinom(1, 1, p.vec)==1
}
logit.data <- mlogit.data(obs,
shape = "long",
choice = "choice",
varying = which( colnames(obs) %in% c('price', 'time', 'bus') ),
alt.var = 'mode')
Here are the first few rows of the generated dataset:
> head(logit.data)
mode price time bus agent.id choice util
1.red.bus red.bus 0.7113747 9.700200 1 1 FALSE -21.306406
1.train train 5.2730015 5.908244 0 1 TRUE -11.181246
1.car car 12.8485015 2.256558 0 1 FALSE -15.105060
2.red.bus red.bus 1.7021472 9.642485 1 2 TRUE -7.677141
2.train train 5.2443204 5.671528 0 2 FALSE -10.915848
2.car car 10.2686018 2.250377 0 2 FALSE -12.518979
I attempt to fit the correctly specified model with the mlogit
package, but I find that the estimates are wrong (the standard deviation of the random effect, in particular):
m.mixed <- mlogit(choice ~ price + time + bus | 0,
data=logit.data,
rpar= c(bus = 'n'),
R = 300, halton = NA)
summary(m.mixed)
> summary(m.mixed)
Call:
mlogit(formula = choice ~ price + time + bus | 0, data = logit.data,
rpar = c(bus = "n"), R = 300, halton = NA)
Frequencies of alternatives:
car red.bus train
0.1317 0.4084 0.4599
bfgs method
8 iterations, 0h:1m:55s
g'(-H)^-1g = 594
last step couldn't find higher value
Coefficients :
Estimate Std. Error t-value Pr(>|t|)
price -1.253720 0.026698 -46.9592 < 2.2e-16 ***
time -1.329888 0.032389 -41.0603 < 2.2e-16 ***
bus 1.402522 0.318802 4.3993 1.086e-05 ***
sd.bus 19.455180 2.107521 9.2313 < 2.2e-16 ***
The true sd.bus
is 10, but mlogit
estimates it at almost 20.
Why isn't mlogit recovering the true model?
set.seed(i)
for theì
-th run), and collecting thesd.bus
estimates. The minimum is 9.0, the mean 18.0, the maximum 33.0. Something indeed seems to be off here. $\endgroup$rep(1:n.samples, each=length(price))
should berep(1:n.samples, each = 3)
. $\endgroup$