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. This may take a day or two at busy times. There is no need to submit the post multiple times.

Are latent variables in Hybrid choice model correlated?

Ask questions about model specifications. Ideally include a mathematical explanation of your proposed model.
Post Reply
rafael_lionello
Posts: 10
Joined: 26 Apr 2020, 04:24

Are latent variables in Hybrid choice model correlated?

Post by rafael_lionello »

Dear Professor Hess,

I am fitting a Hybrid Choice Model with a bi-factor specification for the latent variable component. That is, I have two specific latent variables (e.g., LV1 and LV2 with three ordered indicators each) and a general latent variable (e.g., G). In such a model, the general latent variable has all indicators of specific ones (e.g, six ordered indicators). Moreover, the latent variables are orthogonal (they are not allowed to covary).

Since in SEM packages (e.g., MPLUS) it is commom that latent variables are correlated by default, I would like to know how Apollo treats that.

In a Hybrid Choice Model with two or more latent variables, are these latent variables correlated by default? If yes, how can I set correlation among G and LV1, G and LV2, and L1 and L2 to zero?

Thank you very much for your time.

best, rafael.
stephanehess
Site Admin
Posts: 998
Joined: 24 Apr 2020, 16:29

Re: Are latent variables in Hybrid choice model correlated?

Post by stephanehess »

Hi Rafael

in Apollo, latent variables are just random components in the same way as random coefficients in a mixed logit model. Whether or not they are correlated depends entirely on you and the specification you use.

So if you have:

Code: Select all

apollo_draws = list(
  ...
  interNormDraws = c("eta1","eta2", "eta3"),    
  ...
)

apollo_randCoeff = function(apollo_beta, apollo_inputs){
  randcoeff = list()
  randcoeff[["LV1"]]=gamma_female_LV1*female + sigma1*eta1
  randcoeff[["LV2"]]=gamma_female_LV2*female + sigma2*eta2
  randcoeff[["LVG"]]=gamma_female_LVG*female + sigma3*eta3
  return(randcoeff)
}
then the three LVs are not correlated in the random part but only as a result of using gender as a covariate. You would need to decide whether you normalise the three sigmas to 1 or fix the impact of the in one indicator for each LV.

If you want to allow for correlation, then you could use something like this:

Code: Select all

apollo_randCoeff = function(apollo_beta, apollo_inputs){
  randcoeff = list()
  randcoeff[["LV1"]]=gamma_female_LV1*female + sigma1*eta1
  randcoeff[["LV2"]]=gamma_female_LV2*female + sigma21*eta1 + sigma2*eta2
  randcoeff[["LVG"]]=gamma_female_LVG*female + sigma31*eta1 + sigma32*eta2 + sigma3*eta3
  return(randcoeff)
}
That way, you would estimate the correlation between the LVs, with e.g. the covariance of the random part for LV1 and LV2 being sigma1*sigma21. Again, you would need to think about normalisation of the model

Hope this helps

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
manes
Posts: 16
Joined: 15 Jun 2023, 13:13
Location: Israel
Contact:

Re: Are latent variables in Hybrid choice model correlated?

Post by manes »

Hello,
I have estimated HCM with two latent variables (LV1 and LV2) both are assumed as random vars.
There is a reason to believe that they are positively correlated. To test this assumption I specified the following:

Code: Select all

apollo_draws = list(
  ...
  interNormDraws = c("eta1","eta2"),    
  ...
)
 randcoeff[["LV1"]]=( gamma_car_time_LV1* car_time +eta_LV1)
randcoeff[["LV2"]]=(gamma_female_LV2* female+ gamma_car_time_LV2*car_time+ [b]sigma_LV1_LV2*eta[/b]_LV1+ eta_LV1)

The result indicated a positive and significant sigma_LV1_LV2
Is this indeed an indication of a correlation between LV1 and LV2?
Thanks,
Anat
Anat Tchetchik
stephanehess
Site Admin
Posts: 998
Joined: 24 Apr 2020, 16:29

Re: Are latent variables in Hybrid choice model correlated?

Post by stephanehess »

Hi

can you show us the entire code as it's not clear where eta1 and eta2 are used as you later only use eta_LV1

But it's certainly possible, you just need to think about identification too

Stephane
--------------------------------
Stephane Hess
www.stephanehess.me.uk
manes
Posts: 16
Joined: 15 Jun 2023, 13:13
Location: Israel
Contact:

Re: Are latent variables in Hybrid choice model correlated?

Post by manes »

Sure,
I put down the entire code (just in case..), the relevant part is in the random coefficient specification for the latent variables: NIR-skeptic and Norm .
Short background: the model estimates the choice between leased ICE and hybrid vehicles accounting for concern of non-ionizing radiation (NIR).
There are actually 3 latent variables:
(1) NIR-skeptic (i.e. being skeptic about hybrid cars related NIR risk)
(2) Norm (i.e. having friends and family driving hybrid car) and
(3) Env (i.e. environmental concerns).
There is a fourth attitudinal factor ( NIR- dread) which was not included as a latent var. (it was too much to have 4 LVs)
The assumed positive correlation is between: NIR-skeptic and Norm .

I specified the param: sigma_skeptic_norm , and the random coefficient specification for Norm is:
randcoeff[["norm"]]=(gamma_female_norm * female+ gamma_car_time_total_norm*car_time_total+sigma_skeptic_norm*eta_radiationskeptic+eta_norm )

The question is whether this captures the any possible correlation between NIR-skeptic and Norm..

According to a reviewer (in transportation research part.. ), if this is the case, we should have an interaction term in the utility function that would allow an additional effect when both LVs. are high.

Code: Select all

database=read.csv("data_wide_MNL.csv",header=TRUE)
apollo_beta=  c(asc_ice     =0,
                asc_hybrid_mu   = 0,
                asc_hybrid_sig = 1,
                asc_hybrid_shift_total_car_time = 0,
                b_log_cost_mu = -3,
                b_log_cost_sig=0,
                b_log_radiation_mu   =-5.180016,
                b_log_radiation_sig= 3.632335,
                b_log_radiation_shift_drive_kids=-0.4,
                b_safety = 0.0271929,
                b_hp     = 0.0014011,
                b_trunk= 0.00260, 
                b_emission= -0.03,
                b_no_framing=0.12,
                b_NIR_dread_5=-0.1,
                lambda_radiationskeptic = 0.17,
                lambda_norm=0.55,
                lambda_env= -0.05,
                sigma_skeptic_norm=0.380,
                
                gamma_car_time_total_skeptic =   0.075693,
                gamma_car_time_total_norm   =    0.150556,
                gamma_female_norm   =   -0.14,
                gamma_age_env= 0.26,
                gamma_female_env= 0.16,
                
                tau_radiationskeptic_11          =-2,  
                tau_radiationskeptic_12          =-0.1,
                tau_radiationskeptic_13          = 2,  
                tau_radiationskeptic_14          = 4,
                
                tau_radiationskeptic_21          = -4,  
                tau_radiationskeptic_22          = -2,
                tau_radiationskeptic_23          =  2,  
                tau_radiationskeptic_24          =  4,
                
                tau_radiationskeptic_31          = -3,  
                tau_radiationskeptic_32          = -1,
                tau_radiationskeptic_33          =  3,  
                tau_radiationskeptic_34          =  4,
                
                tau_norm_11                       =-2, 
                tau_norm_12                      =-1,
                tau_norm_13                      = 1,  
                tau_norm_14                      = 2,
                
                tau_norm_21                      =-2, 
                tau_norm_22                      =-1,
                tau_norm_23                      = 1,  
                tau_norm_24                     = 2,
                
                
                tau_norm_31          =-2,  
                tau_norm_32          =-1,
                tau_norm_33          = 1,  
                tau_norm_34          = 2,
                
                tau_env_11          =-4, 
                tau_env_12          =-3,
                tau_env_13          = 0.15,  
                tau_env_14          = 2.5,
                
                tau_env_21          =-3.7, 
                tau_env_22          =-2,
                tau_env_23          = -0.28,  
                tau_env_24          = 1.4,
                
                tau_env_31          =-4,  
                tau_env_32          =-2,
                tau_env_33          = -0.5,  
                tau_env_34          = 4,
                
                tau_env_41          =-3,  
                tau_env_42          =-1.4,
                tau_env_43          = -0.3,  
                tau_env_44          = 2.5,
                
                zeta_radiationskeptic_skeptic_zero_health_risk  = 2.6,  
                zeta_radiationskeptic_skeptic_no_proofs     = 2.5, 
                zeta_radiationskeptic_skeptic_too_short_exposure  = 2.7,
                
                zeta_norm_obs_colleag_use_hyb  = 2.4, 
                zeta_norm_obs_freind_family    = 2.3, 
                zeta_norm_obs_hyb_onroad  = 1.5,
                
                zeta_env_buy_ecofriendly_goods  = 2.5, 
                zeta_env_recycle  = 1.5, 
                zeta_env_green_goods  = 3.8,
                zeta_env_support_activism =1.7)

apollo_fixed = c("asc_ice")


apollo_draws = list(
  interDrawsType = "halton", 
  interNDraws    = 500,          
  interNormDraws = c("draws_hybrid","draws_radiation", "eta_radiationskeptic", "eta_norm", "eta_env", "draws_cost")
)

apollo_randCoeff = function(apollo_beta, apollo_inputs){
randcoeff = list()
randcoeff[["b_cost"]]=  -exp(b_log_cost_mu+ b_log_cost_sig*draws_cost)
randcoeff[["asc_hybrid"]] = asc_hybrid_mu + asc_hybrid_sig * draws_hybrid +asc_hybrid_shift_total_car_time*car_time_total
randcoeff[["b_radiation"]] = -exp(b_log_radiation_mu + b_log_radiation_sig * draws_radiation+b_log_radiation_shift_drive_kids*drive_kids)  randcoeff[["radiationskeptic"]]=( gamma_car_time_total_skeptic* car_time_total  +eta_radiationskeptic)
randcoeff[["norm"]]=(gamma_female_norm * female+ gamma_car_time_total_norm*car_time_total+                         
              sigma_skeptic_norm*eta_radiationskeptic+eta_norm)
randcoeff[["env"]]=( gamma_age_env * age_group+gamma_female_env*female+eta_env )
  return(randcoeff)
}

apollo_inputs = apollo_validateInputs()


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()
  ol_settings1 = list(outcomeOrdered = env_buy_ecofreindly_goods,
                      V =    zeta_env_buy_ecofriendly_goods *env,
                      tau = list(tau_env_11, tau_env_12, tau_env_13, tau_env_14),
                      rows = (task_no==1),
                      componentName = "indic_env_1")      
  
  ol_settings2 = list(outcomeOrdered = env_recycle,
                      V = zeta_env_recycle*env,
                      tau = list(tau_env_21, tau_env_22, tau_env_23, tau_env_24),
                      rows = (task_no==1),
                      componentName = "indic_env_2")
  
  ol_settings3 = list(outcomeOrdered = env_buy_green_goods,
                      V = zeta_env_green_goods*env,
                      tau = list(tau_env_31, tau_env_32, tau_env_33, tau_env_34),
                      rows = (task_no==1), 
                      componentName = "indic_env_3")
  
  ol_settings4 = list(outcomeOrdered = env_support_activism,
                      V = zeta_env_support_activism*env,
                      tau = list(tau_env_41, tau_env_42, tau_env_43, tau_env_44),
                      rows = (task_no==1),
                      componentName = "indic_env_4")
  ol_settings5 = list(outcomeOrdered = skeptic_zero_health_risk,
                      V =  zeta_radiationskeptic_skeptic_zero_health_risk*radiationskeptic,
                      tau = list(tau_radiationskeptic_11, tau_radiationskeptic_12, tau_radiationskeptic_13, tau_radiationskeptic_14),
                      rows = (task_no==1),
                      componentName = "indic_radiationskeptic_1")
  
  ol_settings6 = list(outcomeOrdered = skeptic_no_proofs,
                      V = zeta_radiationskeptic_skeptic_no_proofs*radiationskeptic,
                      tau = list(tau_radiationskeptic_21, tau_radiationskeptic_22, tau_radiationskeptic_23, tau_radiationskeptic_24),
                      rows = (task_no==1),
                      componentName = "indic_radiationskeptic_2")
  
  
  ol_settings7 = list(outcomeOrdered = skeptic_too_short_exposure,             
                      V = zeta_radiationskeptic_skeptic_too_short_exposure*radiationskeptic,
                      tau = list(tau_radiationskeptic_31, tau_radiationskeptic_32, tau_radiationskeptic_33, tau_radiationskeptic_34),
                      rows = (task_no==1), 
                      componentName = "indic_radiationskeptic_3")
  
  ol_settings8 = list(outcomeOrdered = obs_colleag_use_hyb,             
                      V = zeta_norm_obs_colleag_use_hyb*norm,
                      tau = list(tau_norm_11, tau_norm_12, tau_norm_13, tau_norm_14),
                      rows = (task_no==1), 
                      componentName = "indic_norm_1") 
  
  ol_settings9 = list(outcomeOrdered = obs_freind_family,             
                      V = zeta_norm_obs_freind_family*norm,
                      tau = list(tau_norm_21, tau_norm_22, tau_norm_23, tau_norm_24),
                      rows = (task_no==1), 
                      componentName = "indic_norm_2") 
  
  ol_settings10 = list(outcomeOrdered = obs_hyb_onroad,             
                       V = zeta_norm_obs_hyb_onroad*norm,
                       tau = list(tau_norm_31, tau_norm_32, tau_norm_33, tau_norm_34),
                       rows = (task_no==1), 
                       componentName = "indic_norm_3") 
  
  P[["indic_env_1"]] = apollo_ol(ol_settings1, functionality) 
  P[["indic_env_2"]] = apollo_ol(ol_settings2, functionality) 
  P[["indic_env_3"]] = apollo_ol(ol_settings3, functionality)
  P[["indic_env_4"]] = apollo_ol(ol_settings4, functionality)
  P[["indic_radiationskeptic_1"]] = apollo_ol(ol_settings5, functionality)
  P[["indic_radiationskeptic_2"]] = apollo_ol(ol_settings6, functionality)
  P[["indic_radiationskeptic_3"]] = apollo_ol(ol_settings7, functionality)
  P[["indic_norm_1"]] = apollo_ol(ol_settings8, functionality) 
  P[["indic_norm_2"]] = apollo_ol(ol_settings9, functionality) 
  P[["indic_norm_3"]] = apollo_ol(ol_settings10, functionality)
  
  V=list()
  V[["hybrid"]] = asc_hybrid  + b_cost * hybrid_cost + b_radiation * hybrid_radiation + b_safety *hybrid_safety + b_hp * hybrid_hp + b_trunk*hybrid_trunk+ b_emission*hybrid_emission +lambda_radiationskeptic*radiationskeptic*hybrid_radiation+lambda_norm*norm +b_no_framing*no_frame*hybrid_radiation+b_NIR_dread_5*high_NIR_fear_facror_5*hybrid_radiation 
  V[["ice"]]  = asc_ice  +  b_cost * ice_cost +  b_radiation * ice_radiation + b_safety * ice_safety +    b_hp * ice_hp + b_trunk*ice_trunk+  b_emission*ice_emission+lambda_env*env*ice_emission
  
  mnl_settings = list(
    alternatives  = c(ice=1, hybrid=2),
    choiceVar     = choice,
    V     = V
    #componentName = "choice"
  )
  
 P[['choice']] = apollo_mnl(mnl_settings, functionality)
 
 P = apollo_combineModels(P, apollo_inputs, functionality)
 P = apollo_panelProd(P, apollo_inputs, functionality)
 P = apollo_avgInterDraws(P, apollo_inputs, functionality)
 P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)

Anat Tchetchik
manes
Posts: 16
Joined: 15 Jun 2023, 13:13
Location: Israel
Contact:

Re: Are latent variables in Hybrid choice model correlated?

Post by manes »

Please ignore the last part of the post "According to a reviewer (in transportation research part.. ), if this is the case, we should have an interaction term in the utility function that would allow an additional effect when both LVs. are high."
It is not relevant.. sorry for that.
Anat Tchetchik
dpalma
Posts: 190
Joined: 24 Apr 2020, 17:54

Re: Are latent variables in Hybrid choice model correlated?

Post by dpalma »

Hi,

If the model looks identified, then it should be ok. We didn't find any issues with the code.

Best
David
manes
Posts: 16
Joined: 15 Jun 2023, 13:13
Location: Israel
Contact:

Re: Are latent variables in Hybrid choice model correlated?

Post by manes »

Thanks a lot!
Anat Tchetchik
Post Reply