Strong differences in WTP and utility space estimations using mixed logit model
Posted: 24 Mar 2025, 15:32
Hi all,
I estimate a mixed logit model in WTP space with uncorrelated random parameters. Survey respondents could choose between two program alternatives and a status quo. The program options have three attributes, including a payment attribute (which how much respondent would be paid in compensation for participating in the programme described by the other attributes).
Some information about the model in WTP space:
However, transforming the MXL in preference space into WTP space leads to issues.
The results for the MXL in WTP-space strongly differ strongly from the initial utility-space MXL estimations, in sizes, the sign, and significance level (p-value & t-statistic) We conducted different approaches, which have not led to a result close to the utility space estimations:
Below, I attached the code we used in R.
Thank you very much, and best regards,
Moritz
I estimate a mixed logit model in WTP space with uncorrelated random parameters. Survey respondents could choose between two program alternatives and a status quo. The program options have three attributes, including a payment attribute (which how much respondent would be paid in compensation for participating in the programme described by the other attributes).
Some information about the model in WTP space:
- I specify normal distributions for the non-cost attributes and a positive log-normal for the payment attribute.
- The payment attribute is continuous; the other three contract attributes are dummy-coded. In addition, an ASC is included (normally distributed).
- Organizer: Government (ref. level, omitted), Retailer (level 1), NGO (level 2).
- Compensation: Transfer (ref. level, omitted), Label (level 1)
- FC: No FC (ref. level, omitted), FC optional (level 1), FC required (level 2).
- We use Sobol draws, as we are using more than five random coefficients (cf. Bhat, 2003), with 3000 inter draws (recommended by Czajkowski & Budzinski)
However, transforming the MXL in preference space into WTP space leads to issues.
Code: Select all
V = list()
V[['A']] = b_cost * (b_asc + b_retailer * retailer_a + b_ngo * ngo_a + b_label * label_a + b_optional * optional_a + b_required * required_a + cost_a)
V[['B']] = b_cost * (b_asc + b_retailer * retailer_b + b_ngo * ngo_b + b_label * label_b + b_optional * optional_b + b_required * required_b + cost_b)
V[['C']] = 0- tested different prior values (from the CL in utility-space, CL in WTP-space, MXL in utility-space)
- we varied the position of the ASC in the utility function (V). In other words, we tried to conduct the WTP transformation with the ASC inside the brackets and outside the brackets.
- ASC inside the brackets:
Code: Select all
V[['A']] = b_cost * (b_asc + b_retailer * retailer_a + ...
- ASC outside the brackets:
Code: Select all
V[['A']] = b_asc + b_cost * (b_retailer * retailer_a + ...
- ASC inside the brackets:
- testing different distributions for the ASC parameter (uniform or normal) and payment parameters (non-random, uniform, normal)
- using the EM algorithm
- considering random or fixed cost parameters.
Below, I attached the code we used in R.
Thank you very much, and best regards,
Moritz
Code: Select all
##############################################################################################
#### MXL 1 w.o. interactions (WTP Space) (random cost parameter) WTP CL priors - EM algo ####
##############################################################################################
{
### Clear memory
rm(list = ls())
#to check directory (folder where we are working)
getwd()
# to change working directory
setwd("xxxxxxxxx")
# Load Apollo library
library(apollo)
# Load tidyr library
library(tidyr)
# Load readxl library
library(readxl)
### Initialise code
apollo_initialise()
### Set core controls
apollo_control = list(
modelName ="MXL1model_Paper4_WTP_Space_randomcost_CLL_WPT_priors_EM",
modelDescr ="MXL model in WTP Space for Farmersurvey data (not correlated random parameters) + random cost parameter WTP CL priors + EM algorithm",
indivID ="id",
mixing = TRUE,
nCores = 6
)
# We apply the EM algorithm as suggested by Stephane Hess (https://www.apollochoicemodelling.com/forum/viewtopic.php?t=318)
# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS ####
# ################################################################# #
library(haven)
database <- read.csv("Data_UKNLFR_mf_.csv", header = TRUE)
# ################################################################# #
#### DEFINE MODEL PARAMETERS ####
# ################################################################# #
### Vector of parameters, including any that are kept fixed in estimation
apollo_beta = c(mu_asc = -599.410,
mu_b_retailer = - 66.940,
mu_b_ngo = - 68.540,
mu_b_label = -119.230,
mu_b_optional = 95.270,
mu_b_required = - 35.610,
mu_log_b_cost = - 5,
sigma_asc = 0,
sigma_b_retailer = 0,
sigma_b_ngo = 0,
sigma_b_label = 0,
sigma_b_optional = 0,
sigma_b_required = 0,
sigma_log_b_cost = -2)
### Vector with names (in quotes) of parameters to be kept fixed at their starting value in apollo_beta, use apollo_beta_fixed = c() if none
apollo_fixed = c() # maybe interesting for the latent class model. (independent availability model)
# ################################################################# #
#### DEFINE RANDOM COMPONENTS ####
# ################################################################# #
### Set parameters for generating draws
apollo_draws = list(
interDrawsType = "sobol", # Halton Draws are not recommended for more than five random coefficents (cf. Bhat, 2003). For computing Bayesian efficiency pseudo random draws or pseudo monte carlo are the simplest (ChoiceMetrics, 2018).
interNDraws = 3000, # > 2000 Sobol Draws recommendet by Czajkowski & Budzinski 2019
interUnifDraws = c("draws_asc"),
interNormDraws = c("draws_retailer","draws_ngo","draws_label","draws_optional","draws_required","draws_cost")
)
### Create random parameters
apollo_randCoeff = function(apollo_beta, apollo_inputs){
randcoeff = list()
randcoeff[["b_asc"]] = ( mu_asc + sigma_asc * draws_asc )
randcoeff[["b_retailer"]] = ( mu_b_retailer + sigma_b_retailer * draws_retailer )
randcoeff[["b_ngo"]] = ( mu_b_ngo + sigma_b_ngo * draws_ngo )
randcoeff[["b_label"]] = ( mu_b_label + sigma_b_label * draws_label )
randcoeff[["b_optional"]] = ( mu_b_optional + sigma_b_optional * draws_optional )
randcoeff[["b_required"]] = ( mu_b_required + sigma_b_required * draws_required)
randcoeff[["b_cost"]] = exp( mu_log_b_cost + sigma_log_b_cost * draws_cost )
return(randcoeff)
}
# ################################################################# #
#### GROUP AND VALIDATE INPUTS ####
# ################################################################# #
apollo_inputs = apollo_validateInputs()
# ################################################################# #
#### DEFINE MODEL AND LIKELIHOOD FUNCTION ####
# ################################################################# #
apollo_probabilities=function(apollo_beta, apollo_inputs, functionality="estimate"){
### Function initialization: do not change the following three commands
### Attach inputs and detach after function exit
apollo_attach(apollo_beta, apollo_inputs)
on.exit(apollo_detach(apollo_beta, apollo_inputs))
### Create list of probabilities P
P = list()
### List of utilities: these must use the same names as in mnl_settings, order is irrelevant
V = list()
V[['A']] = b_cost * (b_asc + b_retailer * retailer_a + b_ngo * ngo_a + b_label * label_a + b_optional * optional_a + b_required * required_a + cost_a)
V[['B']] = b_cost * (b_asc + b_retailer * retailer_b + b_ngo * ngo_b + b_label * label_b + b_optional * optional_b + b_required * required_b + cost_b)
V[['C']] = 0
### Define settings for MNL model component
mnl_settings = list(
alternatives = c(A=1, B=2, C=3),
avail = 1,
choiceVar = decision, # depend on the variable used in stata
V = V
)
### Compute probabilities using MNL model
P[['model']] = apollo_mnl(mnl_settings, functionality)
### Take product across observation for same individual
P = apollo_panelProd(P, apollo_inputs, functionality)
### Average across inter-individual draws
P = apollo_avgInterDraws(P, apollo_inputs, functionality)
### Prepare and return outputs of function
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}
# ################################################################# #
#### EM ESTIMATION ####
# ################################################################# #
mixEM_settings = list(transforms=list(function(x) log(-x),
function(x) log(-x),
function(x) log(-x),
function(x) log(-x)))
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs, mixEM_settings)
# ################################################################# #
#### MODEL OUTPUTS ####
# ################################################################# #
# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO SCREEN) ----
# ----------------------------------------------------------------- #
apollo_modelOutput(model, list(printPVal = 2))
# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO FILE, using model name) ----
# ----------------------------------------------------------------- #
apollo_saveOutput(model, list(printPVal = 2))
#################################
# Cost Parameter Transformation #
#################################
# transform the cost parameter. Look up into the Forum follow link to the Forum Post: use method suggested by D Palma : http://www.apollochoicemodelling.com/forum/viewtopic.php?f=16&t=262
# sigma is the standard deviation, mu gives average preference.
apollo_deltaMethod(model, deltaMethod_settings = list(operation="lognormal",parName1="mu_log_b_cost",parName2="sigma_log_b_cost"))
}