I have specified a sequential BW LC (no covariates). It is a case 1 BW with 16 items in total, 8 choice-sets and 4 items per choice set.
In the results, there is a non-sig trend for a lower value estimate of the position-specific constant across alternatives (i.e. a hint of position bias!).
I'd like to explore this further by separating out the ASC for B & W choices, to see if there is a difference in the position effect between best and worst choices, but I can't figure out how to specify it.
Any help appreciated,
Best wishes,
Jay
Code: Select all
# ################################################################# #
#### LOAD LIBRARY AND DEFINE CORE SETTINGS ####
# ################################################################# #
### Clear memory
rm(list = ls())
### Load Apollo library
library(apollo)
### Initialise code
apollo_initialise()
### Set core controls
apollo_control = list(
modelName = "BW_2_LC_no_covariates",
modelDescr = "Simple LC model on BW choice data, no covariates in class allocation model",
indivID = "uuid",
nCores = 2,
outputDirectory = "output"
)
# ################################################################# #
#### LOAD DATA AND APPLY ANY TRANSFORMATIONS ####
# ################################################################# #
### Loading data from package
### if data is to be loaded from a file (e.g. called data.csv),
### the code would be: database = read.csv("data.csv",header=TRUE)
database <- read_csv("apollo/BW_LC_no_covariates.csv") %>%
select(-c(cset, setno, alt1_avail:alt4_avail, csn)) %>%
mutate(across(T1_1:T16_4, ~ if_else(bw == 2, . * -1, .)),
bw = if_else(bw == 1, "best", "worst")) %>%
pivot_wider(names_from = bw, values_from = choice, names_prefix = "choice_") %>%
relocate(c("choice_best", "choice_worst"), .before = "T1_1")
### for data dictionary, use ?apollo_swissRouteChoiceData
# ################################################################# #
#### DEFINE MODEL PARAMETERS ####
# ################################################################# #
### Vector of parameters, including any that are kept fixed in estimation
apollo_beta = c(set_names(rep(0, 38),
c(paste0("asc_alt", 1:4),
paste0("beta_T", rep(1:16, each = 2), "_", letters[1:2]),
paste0("delta_", letters[1:2]))),
mu_worst = 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_alt1", "beta_T2_a", "beta_T2_b", "delta_b")
# ################################################################# #
#### DEFINE LATENT CLASS COMPONENTS ####
# ################################################################# #
apollo_lcPars=function(apollo_beta, apollo_inputs){
lcpars = list()
lcpars[["beta_T1"]] = list(beta_T1_a, beta_T1_b)
lcpars[["beta_T2"]] = list(beta_T2_a, beta_T2_b)
lcpars[["beta_T3"]] = list(beta_T3_a, beta_T3_b)
lcpars[["beta_T4"]] = list(beta_T4_a, beta_T4_b)
lcpars[["beta_T5"]] = list(beta_T5_a, beta_T5_b)
lcpars[["beta_T6"]] = list(beta_T6_a, beta_T6_b)
lcpars[["beta_T7"]] = list(beta_T7_a, beta_T7_b)
lcpars[["beta_T8"]] = list(beta_T8_a, beta_T8_b)
lcpars[["beta_T9"]] = list(beta_T9_a, beta_T9_b)
lcpars[["beta_T10"]] = list(beta_T10_a, beta_T10_b)
lcpars[["beta_T11"]] = list(beta_T11_a, beta_T11_b)
lcpars[["beta_T12"]] = list(beta_T12_a, beta_T12_b)
lcpars[["beta_T13"]] = list(beta_T13_a, beta_T13_b)
lcpars[["beta_T14"]] = list(beta_T14_a, beta_T14_b)
lcpars[["beta_T15"]] = list(beta_T15_a, beta_T15_b)
lcpars[["beta_T16"]] = list(beta_T16_a, beta_T16_b)
V=list()
V[["class_a"]] = delta_a
V[["class_b"]] = delta_b
classAlloc_settings = list(
classes = c(class_a = 1, class_b = 2),
utilities = V
)
lcpars[["pi_values"]] = apollo_classAlloc(classAlloc_settings)
return(lcpars)
}
# ################################################################# #
#### GROUP AND VALIDATE INPUTS ####
# ################################################################# #
apollo_inputs = apollo_validateInputs()
# ################################################################# #
#### DEFINE MODEL AND LIKELIHOOD FUNCTION ####
# ################################################################# #
apollo_probabilities=function(apollo_beta, apollo_inputs, functionality = "estimate"){
### 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()
P_bw = list()
### Define settings for MNL model component that are generic across classes
mnl_settings = list(
alternatives = c(alt1 = 1, alt2 = 2, alt3 = 3, alt4 = 4)
)
### Loop over classes
for(s in 1:2){
### Compute class-specific utilities
V=list()
V[["alt1"]] = asc_alt1 + beta_T1[[s]]*T1_1 + beta_T2[[s]]*T2_1 + beta_T3[[s]]*T3_1 + beta_T4[[s]]*T4_1 +
beta_T5[[s]]*T5_1 + beta_T6[[s]]*T6_1 + beta_T7[[s]]*T7_1 +
beta_T8[[s]]*T8_1 + beta_T9[[s]]*T9_1 + beta_T10[[s]]*T10_1 +
beta_T11[[s]]*T11_1 + beta_T12[[s]]*T12_1 + beta_T13[[s]]*T13_1 +
beta_T14[[s]]*T14_1 + beta_T15[[s]]*T15_1 + beta_T16[[s]]*T16_1
V[["alt2"]] = asc_alt2 + beta_T1[[s]]*T1_2 + beta_T2[[s]]*T2_2 + beta_T3[[s]]*T3_2 + beta_T4[[s]]*T4_2 +
beta_T5[[s]]*T5_2 + beta_T6[[s]]*T6_2 + beta_T7[[s]]*T7_2 +
beta_T8[[s]]*T8_2 + beta_T9[[s]]*T9_2 + beta_T10[[s]]*T10_2 +
beta_T11[[s]]*T11_2 + beta_T12[[s]]*T12_2 + beta_T13[[s]]*T13_2 +
beta_T14[[s]]*T14_2 + beta_T15[[s]]*T15_2 + beta_T16[[s]]*T16_2
V[["alt3"]] = asc_alt3 + beta_T1[[s]]*T1_3 + beta_T2[[s]]*T2_3 + beta_T3[[s]]*T3_3 + beta_T4[[s]]*T4_3 +
beta_T5[[s]]*T5_3 + beta_T6[[s]]*T6_3 + beta_T7[[s]]*T7_3 +
beta_T8[[s]]*T8_3 + beta_T9[[s]]*T9_3 + beta_T10[[s]]*T10_3 +
beta_T11[[s]]*T11_3 + beta_T12[[s]]*T12_3 + beta_T13[[s]]*T13_3 +
beta_T14[[s]]*T14_3 + beta_T15[[s]]*T15_3 + beta_T16[[s]]*T16_3
V[["alt4"]] = asc_alt4 + beta_T1[[s]]*T1_4 + beta_T2[[s]]*T2_4 + beta_T3[[s]]*T3_4 + beta_T4[[s]]*T4_4 +
beta_T5[[s]]*T5_4 + beta_T6[[s]]*T6_4 + beta_T7[[s]]*T7_4 +
beta_T8[[s]]*T8_4 + beta_T9[[s]]*T9_4 + beta_T10[[s]]*T10_4 +
beta_T11[[s]]*T11_4 + beta_T12[[s]]*T12_4 + beta_T13[[s]]*T13_4 +
beta_T14[[s]]*T14_4 + beta_T15[[s]]*T15_4 + beta_T16[[s]]*T16_4
### Compute probabilities for "best" choice using MNL model
mnl_settings$avail = list(alt1 = 1, alt2 = 1, alt3 = 1, alt4 = 1)
mnl_settings$choiceVar = choice_best
mnl_settings$V = V
mnl_settings$componentName = paste0("Best_Class_", s)
## Compute within-class choice probabilities using MNL model
P_bw[["best"]] = apollo_mnl(mnl_settings, functionality)
### Take product across observations for same individual
P_bw[["best"]] = apollo_panelProd(P_bw[["best"]], apollo_inputs, functionality)
### Compute probabilities for "worst" choice using MNL model
mnl_settings$avail = list(alt1 = (choice_best != 1), alt2 = (choice_best != 2), alt3 = (choice_best != 3), alt4 = (choice_best != 4))
mnl_settings$choiceVar = choice_worst
mnl_settings$V = lapply(V, "*", -mu_worst)
mnl_settings$componentName = paste0("Worst_Class_", s)
###Compute within-class choice probabilities using MNL model
P_bw[["worst"]] = apollo_mnl(mnl_settings, functionality)
##Take product across observations for same individual
P_bw[["worst"]] = apollo_panelProd(P_bw[["worst"]], apollo_inputs, functionality)
P[[paste0("Class_", s)]] = apollo_combineModels(P_bw, apollo_inputs, functionality)$model
}
### Compute latent class model probabilities
lc_settings = list(inClassProb = P, classProb = pi_values)
P[["model"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
### Prepare and return outputs of function
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}
# ################################################################# #
#### MODEL ESTIMATION ####
# ################################################################# #
### Optional starting values search
# apollo_beta=apollo_searchStart(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs)
model = apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)
# ################################################################# #
#### MODEL OUTPUTS ####
# ################################################################# #
# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO SCREEN) ----
# ----------------------------------------------------------------- #
apollo_modelOutput(model, modelOutput)
# ----------------------------------------------------------------- #
#---- FORMATTED OUTPUT (TO FILE, using model name) ----
# ----------------------------------------------------------------- #
apollo_saveOutput(model)