Important: Read this before posting to this forum

  1. This forum is for questions related to the use of Apollo. We will answer some general choice modelling questions too, where appropriate, and time permitting. We cannot answer questions about how to estimate choice models with other software packages.
  2. There is a very detailed manual for Apollo available at http://www.ApolloChoiceModelling.com/manual.html. This contains detailed descriptions of the various Apollo functions, and numerous examples are available at http://www.ApolloChoiceModelling.com/examples.html. In addition, help files are available for all functions, using e.g. ?apollo_mnl
  3. Before asking a question on the forum, users are kindly requested to follow these steps:
    1. Check that the same issue has not already been addressed in the forum - there is a search tool.
    2. Ensure that the correct syntax has been used. For any function, detailed instructions are available directly in Apollo, e.g. by using ?apollo_mnl for apollo_mnl
    3. Check the frequently asked questions section on the Apollo website, which discusses some common issues/failures. Please see http://www.apollochoicemodelling.com/faq.html
    4. Make sure that R is using the latest official release of Apollo.
  4. If the above steps do not resolve the issue, then users should follow these steps when posting a question:
    1. provide full details on the issue, including the entire code and output, including any error messages
    2. posts will not immediately appear on the forum, but will be checked by a moderator first. We check the forum at least twice a week. It may thus take a couple of days for your post to appear and before we reply. There is no need to submit the post multiple times.

Mixed logit with latent variable and socio-demographic

Ask questions about model specifications. Ideally include a mathematical explanation of your proposed model.
Post Reply
Xxxxie
Posts: 1
Joined: 12 Dec 2024, 12:20

Mixed logit with latent variable and socio-demographic

Post by Xxxxie »

Dear Stephane,

I am building Mixed Logit Model allowed the inclusion of latent variables. I am interested in understanding whether the two external treatments influence consumers' preferences for attribute2 therefore the interaction term attribute2 * treatment is included, and how individual socio-demographic characteristics and attitudes impact the effects of these treatments.

Specifically, I draw on Hao et al.'s paper (See Hao, F., Qiu, R. T. R., Park, J., & Chon, K. (2023). The Myth of Contactless Hospitality Service: Customers’ Willingness to Pay. Journal of Hospitality & Tourism Research, 47(8), 1478-1502. https://doi.org/10.1177/10963480221081781), where the preference parameter is specified as a function of latent values, which differs from the approach in the Apollo manual (where personal characteristics and latent variables are directly incorporated into the utility function).

Below is my code, though I am unsure if it achieves my aim. Additionally, after implementing this, I don't how to estimate willingness to pay, can you advise accordingly? Many thanks.

# Mixed logit with latent variable and socio-demographic ###
apollo_beta = c(
asc_a = 0,
asc_b = 0,
asc_c = 0,

mu_log_b_attribute1 = 0,
sigma_log_b_attribute1= 1,

mu_log_b_attribute2 = 0,
sigma_log_b_attribute2 = 1,

mu_log_b_attribute2_treat1 = 0,
sigma_log_b_attribute2_treat1= 1,

mu_log_b_attribute2_treat2 = 0,
sigma_log_b_attribute2_treat2= 1,

mu_log_b_attribute3 = 0,
sigma_log_b_attribute3 = 1,

mu_log_b_price = 0,
sigma_log_b_price = 1,

lambda_attribute1_LV1=0,
lambda_attribute1_LV2=0,
lambda_attribute2_LV1=0,
lambda_attribute2_LV2=0,
lambda_attribute2_treat1_LV1=0,
lambda_attribute2_treat1_LV2=0,
lambda_attribute2_treat2_LV1=0,
lambda_attribute2_treat2_LV2=0,
lambda_attribute3_LV1=0,
lambda_attribute3_LV2=0,

b_gender_LV1 = 0,
b_age_LV1 = 0,
b_edu_2_LV1 = 0,
b_edu_3_LV1 = 0,
b_edu_4_LV1 = 0,

b_gender_ES = 0,
b_age_ES = 0,
b_edu_2_ES = 0,
b_edu_3_ES = 0,
b_edu_4_ES = 0,

zeta_LV1_1 = 0,
zeta_LV1_2 = 0,
zeta_LV1_3 = 0,
zeta_LV1_4 = 0,
zeta_LV2_1 = 0,
zeta_LV2_2 = 0,
zeta_LV2_3 = 0,
zeta_LV2_4 = 0,

sigma_LV1_1 = 1,
sigma_LV1_2 = 1,
sigma_LV1_3 = 1,
sigma_LV1_4 = 1,
sigma_LV2_1 = 1,
sigma_LV2_2 = 1,
sigma_LV2_3 = 1,
sigma_LV2_4 = 1,

)

### 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('asc_a')

apollo_draws = list(
interDrawsType="halton",
interNDraws=100,
interUnifDraws=c(),
interNormDraws=c('eta01','eta02','eta03','eta04',

"eta1", 'eta2'),

intraDrawsType="",
intraNDraws=0,
intraUnifDraws=c(),
intraNormDraws=c()
)


apollo_randCoeff=function(apollo_beta, apollo_inputs){
randcoeff = list()

randcoeff[["LV1"]] =
eta1 +
b_gender_LV1 * gender +
b_age_LV1 * age +
b_edu_2_LV1 * edu_2 +
b_edu_3_LV1 * edu_3 +
b_edu_4_LV1 * edu_4

randcoeff[["LV2"]] =
eta2 +
b_gender_LV2 * gender +
b_age_LV2 * age +
b_edu_2_LV2 * edu_2 +
b_edu_3_LV2 * edu_3 +
b_edu_4_LV2 * edu_4

randcoeff[["attribute1coef"]]=mu_log_b_attribute1 + sigma_log_b_attribute1 * eta01
randcoeff[["attribute2coef"]]=mu_log_b_attribute2 + sigma_log_b_attribute2 * eta02
randcoeff[["attribute2coef_treat1"]]=mu_log_b_attribute2_treat1 + sigma_log_b_attribute2_treat1 * eta02
randcoeff[["attribute2coef_treat2"]]=mu_log_b_attribute2_treat2 + sigma_log_b_attribute2_treat2 * eta02
randcoeff[["attribute3coef"]]=mu_log_b_attribute3 + sigma_log_b_attribute3 * eta03
randcoeff[["pricecoef"]]=-exp(mu_log_b_price + sigma_log_b_price * eta04)

return(randcoeff)
}


# ################################################################# #
#### GROUP AND VALIDATE INPUTS ####
# ################################################################# #

apollo_inputs = apollo_validateInputs()

# ################################################################# #
#### DEFINE MODEL AND LIKELIHOOD FUNCTION ####
# ################################################################# #

apollo_probabilities=function(apollo_beta, apollo_inputs, functionality="estimate"){

apollo_attach(apollo_beta, apollo_inputs)
on.exit(apollo_detach(apollo_beta, apollo_inputs))

P = list()


normalDensity_settings1 = list(
outcomeNormal = LV1_1,
xNormal = zeta_LV1_1 * LV1,
mu = 0,
sigma = sigma_LV1_1,
componentName = "indic_LV1_1")

normalDensity_settings2 = list(
outcomeNormal = LV1_2,
xNormal = zeta_LV1_2 * LV1,
mu = 0,
sigma = sigma_LV1_2,
componentName = "indic_LV1_2")

normalDensity_settings3 = list(
outcomeNormal = LV1_3,
xNormal = zeta_LV1_3 * LV1,
mu = 0,
sigma = sigma_LV1_3,
componentName = "indic_LV1_3")

normalDensity_settings4 = list(
outcomeNormal = LV1_4,
xNormal = zeta_LV1_4 * LV1,
mu = 0,
sigma = sigma_LV1_4,
componentName = "indic_LV1_4")

normalDensity_settings21 = list(
outcomeNormal = LV2_1,
xNormal = zeta_LV2_1 * LV2,
mu = 0,
sigma = sigma_LV2_1,
componentName = "indic_LV2_1")

normalDensity_settings22 = list(
outcomeNormal = LV2_2,
xNormal = zeta_LV2_2 * LV2,
mu = 0,
sigma = sigma_LV2_2,
componentName = "indic_LV2_2")

normalDensity_settings23 = list(
outcomeNormal = LV2_3,
xNormal = zeta_LV2_3 * LV2,
mu = 0,
sigma = sigma_LV2_3,
componentName = "indic_LV2_3")

normalDensity_settings24 = list(
outcomeNormal = LV2_4,
xNormal = zeta_LV2_4 * LV2,
mu = 0,
sigma = sigma_LV2_4,
componentName = "indic_LV2_4")

P[["indic_LV1_1"]] = apollo_normalDensity(normalDensity_settings1, functionality)
P[["indic_LV1_2"]] = apollo_normalDensity(normalDensity_settings2, functionality)
P[["indic_LV1_3"]] = apollo_normalDensity(normalDensity_settings3, functionality)
P[["indic_LV1_4"]] = apollo_normalDensity(normalDensity_settings4, functionality)

P[["indic_LV2_1"]] = apollo_normalDensity(normalDensity_settings21, functionality)
P[["indic_LV2_2"]] = apollo_normalDensity(normalDensity_settings22, functionality)
P[["indic_LV2_3"]] = apollo_normalDensity(normalDensity_settings23, functionality)
P[["indic_LV2_4"]] = apollo_normalDensity(normalDensity_settings24, functionality)


attribute1coefLV = attribute1coef + lambda_attribute1_LV1 * LV1 + lambda_attribute1_LV2 * LV2
attribute2coefLV = attribute2coef + lambda_attribute2_LV1 * LV1 + lambda_attribute2_LV2 * LV2
attribute3coefLV = attribute3coef + lambda_attribute3_LV1 * LV1 + lambda_attribute3_LV2 * LV2
attribute2coef_treat1LV = attribute2coef_treat1 + lambda_attribute2_treat1_LV1 * LV1 + lambda_attribute2_treat1_LV2 * LV2
attribute2coef_treat2LV = attribute2coef_treat2 + lambda_attribute2_treat2_LV1 * LV1 + lambda_attribute2_treat2_LV2 * LV2

V = list()

V[['a']] = asc_a +
attribute2coefLV * attribute2A +
attribute2coef_treat1LV * attribute2A * treatment1+
attribute2coef_treat2LV * attribute2A * treatment2+
attribute1coefLV * attribute1A +
attribute3coefLV * attribute3A +
pricecoef * priceA

V[['b']] = asc_b +
attribute2coefLV * attribute2B+
attribute2coef_treat1LV * attribute2B * treatment1 +
attribute2coef_treat2LV * attribute2B * treatment2 +
attribute1coefLV * attribute1B +
attribute3coefLV * attribute3B +
pricecoef * priceB

V[['c']] = asc_c +
attribute2coefLV * attribute2C+
attribute2coef_treat1LV * attribute2C * treatment1 +
attribute2coef_treat2LV * attribute2C * treatment2 +
attribute1coefLV * attribute1C +
attribute3coefLV * attribute3C +
pricecoef * priceC


mnl_settings = list(
alternatives = c(a = 'a', b = 'b', c = 'c'),
# avail = list(Q1=1, N2=1, Q3=1),
choiceVar = choice,
utilities = V,
componentName = "choice"
)
### Compute probabilities for MNL model component
P[["choice"]] = apollo_mnl(mnl_settings, functionality)

### Likelihood of the whole model
P = apollo_combineModels(P, apollo_inputs, 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)
}


model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs,
estimate_settings = list(estimationRoutine = "bfgs",
maxIterations = 1000))
stephanehess
Site Admin
Posts: 1355
Joined: 24 Apr 2020, 16:29

Re: Mixed logit with latent variable and socio-demographic

Post by stephanehess »

Hi

in the online examples, we interact the LVs with the ASCs. It's the same principle as interacting them with betas that multiply attributes.

You can then either do that inside apollo_randCoeff, e.g.

randCoeff[["beta"]] = mu_beta + sigma_beta * draws_beta + tau_beta_LV1 * randcoeff[["LV1"]]

or inside apollo_probabilities. The above is probably easier.

Note that in my example above, I also have independent random heterogeneity to ensure that the model does not misassociate the impact of the LV. Have a look at https://www.sciencedirect.com/science/a ... 452030049X

Also, in your code, you refer to eta1 in the LV when that is not defined anywhere. I assume you mean eta01. But in the coefficients, you should then include the entire LV, not just the random part eta

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
Post Reply