Basic Usage

Estimating models

The logitr() function estimates multinomial logit (MNL) and mixed logit (MXL) models using “Preference” space or “Willingness-to-pay (WTP)” space utility parameterizations. The basic usage for estimating models is as follows:

model <- logitr(
  data,
  choiceName,
  obsIDName,
  parNames,
  priceName = NULL,
  randPars = NULL,
  randPrice = NULL,
  modelSpace = "pref",
  weightsName = NULL,
  options = list()
)

Data format

The data.frame provided to the data argument must be arranged in a particular way (i.e. “long” or “tidy” format). Each row should be an alternative from a choice observation. The choice observations do not have to be symmetric (i.e. each choice observation could have a different number of alternatives). The data must include columns for each of the following arguments in the logitr() function:

  1. choiceName: A dummy variable that identifies which alternative was chosen (1 = chosen, 0 = not chosen).
  2. obsIDName: A sequence of numbers that identifies each unique choice occasion. For example, if the first three choice occasions had 2 alternatives each, then the first 9 rows of the obsID variable would be .
  3. parNames: The names of the variables that will be used as model covariates. For WTP space models, do not include the price variable in parNames - this is provided separately with the priceName argument.

The data sets included in this package all follow this format (e.g. the yogurt data set).

You can read more details in the “Data Formatting and Encoding” vignette.

Preference space models

Unlike similar packages like mlogit, logitr does not support the formula type input that uses a symbolic description of the model to be estimated. Parameters are simply described as a vector of the column names in the data.frame provided to the data argument.

The logitr() function assumes that the deterministic part of the utility function, \(v_{j}\), is linear in parameters, i.e.:

\[\begin{equation} u_{j} = v_{j} + \varepsilon_{j} \hspace{0.5in} \varepsilon_{j} \sim \textrm{Gumbel}\left(0,\frac{\pi^2}{6}\right) \label{eq:utilityComponents} \end{equation}\]

\[\begin{equation} v_{j} = \mathbf{β}' \mathrm{\mathbf{x}}_{j} - \alpha p_{j} \hspace{0.5in} \label{eq:utilityPreferenceObserved} \end{equation}\]

where \(\mathbf{β}\) is the vector of coefficients for non-price attributes \(\mathrm{\mathbf{x}}_{j}\), \(\alpha\) is the coefficient for price \(p_{j}\). Accordingly, each parameter in the parNames argument is an additive part of \(v_{j}\).

For example, if the observed utility was \(v_{j} = \beta x_{j} - \alpha p_{j}\), where \(p_{j}\) is “price” and \(x_{j}\) is “size”, then the parNames argument should be c("price", "size"). Such an example could be estimated with the following code, where the data object is a data.frame with columns named "choice", "obsID", "price", and "size":

mnl_pref <- logitr(
    data       = data,
    choiceName = "choice",
    obsIDName  = "obsID",
    parNames   = c("price", "size"))
)

WTP space models

For models estimated in the WTP space, the modelSpace argument should be set to modelSpace = "wtp". The parNames argument should not contain the name of the column for the price attribute as it should be provided separately with the priceName argument.

For example, if the observed utility was \(v_{j} = \lambda \left(\omega x_{j} - p_{j}\right)\), where \(p_{j}\) is “price” and \(x_{j}\) is “size”, then the parNames argument should be "size" and the priceName argument should be "price". Such an example could be estimated with the following code, where the data object is a data.frame with columns named "choice", "obsID", "price", and "size":

mnl_wtp <- logitr(
    data       = data,
    choiceName = "choice",
    obsIDName  = "obsID",
    parNames   = "size",
    priceName  = "price",
    modelSpace = "wtp",
    options    = list(numMultiStarts = 10) # Set numMultiStarts > 1 to run a multistart
)

Since WTP space models are non-convex, it is recommended that you use a multi-start search to run the optimization loop multiple times to search for different local minima:

Mixed logit models

To estimate a mixed logit model, use the randPars argument to denote which parameters will be modeled with a distribution. The current package version supports normal and log-normal distributions.

For example, if the observed utility was \(v_{j} = \beta x_{j} - \alpha p_{j}\), where \(p_{j}\) is “price” and \(x_{j}\) is “size” and you wanted to model the "size" parameter, \(\beta\), with a normal or log-normal distribution, set randPars = c(size = "n") or randPars = c(size = "ln"):

mxl_pref <- logitr(
    data       = data,
    choiceName = "choice",
    obsIDName  = "obsID",
    parNames   = c("price", "size"),
    randPars   = c(size = "n"), # Modeling size parameter as normally distributed
    options    = list(numMultiStarts = 10) # Set numMultiStarts > 1 to run a multistart
)

Since mixed logit models are non-convex, it is recommended that you use a multi-start search to run the optimization loop multiple times to search for different local minima. Note that mixed logit models can take a long time to estimate, so setting large number for numMultiStarts could take hours or longer to complete.

View results

Use the summary() function to print a summary of the results from an estimated model. The function will print the following based on the model settings:

Use statusCodes() to print a description of each status code from the nloptr optimization routine.

Computing and comparing WTP

For models in the preference space, you can get a summary table of the implied WTP by using:

wtp(mnl_pref, priceName)

To compare the WTP between two equivalent models in the preference space and WTP spaces, use:

wtpCompare(mnl_pref, mnl_wtp, priceName)

Simulate shares

Once you have estimated a model, you can use it to simulate the expected shares of a particular set of alternatives. This can be done using the function simulateShares(). The simulation reports the expected share as well as a confidence interval for each alternative:

shares = simulateShares(model, alts, priceName = NULL, alpha = 0.025)