stephanehess wrote: 13 Aug 2024, 17:15
Hi
you need to put Q into apollo_inputs after the line
Code: Select all
apollo_inputs = apollo_validateInputs()
using
and then everywhere else in apollo_lcPars and apollo_probabilities, you need to replace Q by apollo_inputs$Q
Stephane
Hi Stephane,
This recommendation addressed an issue I was encountering when trying to develop a script to estimate an LCL with a variable number of classes & pass the parameter n_classes to write variables dynamically for each LCL class. However, I now encounter an issue with lcpars during initialization, which needs to access apollo_inputs$n_classes, which is not defined until after apollo_validateInputs().
Alternatively, it was working when I assigned database$n_classes, but I don't think that makes sense to do for a parameter & gave the warning "Warning: numerical expression has 11010 elements: only the first usedWarning: numerical expression has 11010 elements: only the first used".
Overall, I am trying to set up code to be able to run over a range of LCL classes. How can I define n_classes in a way that it can be passed to apollo_lcPars & apollo_probabilities?
Thank you for your assistance & for developing Apollo.
You can find my code, output, & the error below:
# Initialize Apollo
apollo_initialise()
# Set up core control parameters
apollo_control <- list(
modelName = "LCL_CarChoice_Full",
modelDescr = "Latent Class Logit Model for Car Choice",
indivID = "ID",
panelData = TRUE,
nCores = 8,
mixing = FALSE, # No mixing in LCL
weights = 'Weight2018',
outputDirectory = "output/"
)
# Assign the dataframe to 'database'
database <- cbc_short_car_df
# Number of classes (to be changed dynamically)
n_classes <- 2
# Initialize the parameters list for each class
apollo_beta <- c()
# Loop to define parameters for each class
for (i in 1:n_classes) {
# Defining parameters for each class (b_price, b_acceleration, etc.)
apollo_beta <- c(apollo_beta,
setNames(i*-.1, paste0("b_price_", i)),
setNames(0, paste0("b_acceleration_", i)),
setNames(0, paste0("b_opcost_", i)),
setNames(0, paste0("b_bev_", i)),
setNames(0, paste0("b_bevRangeRel_", i)),
setNames(0, paste0("b_phev20_", i)),
setNames(0, paste0("b_phev40_", i)),
setNames(0, paste0("b_hev_", i)),
setNames(0, paste0("class_intercept_", i))
)
}
# Fixed parameters
apollo_fixed <- c("class_intercept_1")
apollo_lcPars <- function(apollo_beta, apollo_inputs){
lcpars = list()
# Loop to define the class-specific parameters for vehicle choice
print("Print value for 'apollo_inputs$n_classes':")
print(apollo_inputs$n_classes)
n <- apollo_inputs$n_classes
for (i in 1:n) {
lcpars[['b_price']][
] <- get(paste0('b_price_', i))
lcpars[['b_acceleration']][] <- get(paste0('b_acceleration_', i))
lcpars[['b_opcost']][] <- get(paste0('b_opcost_', i))
lcpars[['b_bev']][] <- get(paste0('b_bev_', i))
lcpars[['b_bevRangeRel']][] <- get(paste0('b_bevRangeRel_', i))
lcpars[['b_phev20']][] <- get(paste0('b_phev20_', i))
lcpars[['b_phev40']][] <- get(paste0('b_phev40_', i))
lcpars[['b_hev']][] <- get(paste0('b_hev_', i))
# Parameters for the probability of class membership
lcpars[['class_intercept']][] <- get(paste0('class_intercept_', i))
}
# Define utilities for class allocation model (for class membership probability)
V = list()
# Class allocation
class_arg <- c()
for (j in 1:n) {
V[[paste0('class_', j)]] <- 0
V[[paste0('class_', j)]] <- V[[paste0('class_', j)]] + get(paste0('class_intercept_', j))
class_arg[paste0('class_', j)] <- j
}
# Settings for the class allocation model
classAlloc_settings = list(
classes = class_arg, # Dynamic class names
utilities = V
)
# Compute the class probabilities (pi_values)
lcpars[["pi_values"]] = apollo_classAlloc(classAlloc_settings)
return(lcpars)
}
# Validate inputs
apollo_inputs <- apollo_validateInputs()
apollo_inputs$n_classes <- n_classes
# Define probabilities function for LCL with 2 classes
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()
# Call apollo_lcPars to get the class parameters and pi_values
lcpars = apollo_lcPars(apollo_beta, apollo_inputs)
# Loop over classes
print("Printing value of 'apollo_inputs$n_classes'")
print(apollo_inputs$n_classes)
for (s in 1:apollo_inputs$n_classes) {
# Define class-specific utilities for each alternative
V = list()
# For each alternative, define its utility for class `s`
V[["C1"]] =
get(paste0("b_price_", s)) * PriceC1 +
get(paste0("b_acceleration_", s)) * AccelerationC1 +
get(paste0("b_opcost_", s)) * OpCostC1 +
get(paste0("b_bev_", s)) * bevC1 +
get(paste0("b_bevRangeRel_", s)) * bevRangeRelC1 +
get(paste0("b_phev20_", s)) * phev20C1 +
get(paste0("b_phev40_", s)) * phev40C1 +
get(paste0("b_hev_", s)) * hevC1
V[["C2"]] =
get(paste0("b_price_", s)) * PriceC2 +
get(paste0("b_acceleration_", s)) * AccelerationC2 +
get(paste0("b_opcost_", s)) * OpCostC2 +
get(paste0("b_bev_", s)) * bevC2 +
get(paste0("b_bevRangeRel_", s)) * bevRangeRelC2 +
get(paste0("b_phev20_", s)) * phev20C2 +
get(paste0("b_phev40_", s)) * phev40C2 +
get(paste0("b_hev_", s)) * hevC2
V[["C3"]] =
get(paste0("b_price_", s)) * PriceC3 +
get(paste0("b_acceleration_", s)) * AccelerationC3 +
get(paste0("b_opcost_", s)) * OpCostC3 +
get(paste0("b_bev_", s)) * bevC3 +
get(paste0("b_bevRangeRel_", s)) * bevRangeRelC3 +
get(paste0("b_phev20_", s)) * phev20C3 +
get(paste0("b_phev40_", s)) * phev40C3 +
get(paste0("b_hev_", s)) * hevC3
# Define settings for MNL model component
mnl_settings = list(
alternatives = c(C1=1, C2=2, C3=3),
choiceVar = Choice, # Assuming `Choice` is the choice variable in your dataset
utilities = V
)
# Compute within-class choice probabilities using MNL model
P[[paste0("Class_", s)]] = apollo_mnl(mnl_settings, functionality)
# Take product across observation for same individual
P[[paste0("Class_", s)]] = apollo_panelProd(P[[paste0("Class_", s)]], apollo_inputs, functionality)
}
# Compute latent class model probabilities (combining all classes)
lc_settings = list(
inClassProb = P, # Probabilities from each class
classProb = pi_values # Class probabilities (e.g., `delta_1`, `delta_2`)
)
# Calculate the overall model probabilities using latent class model
P[["model"]] = apollo_lc(lc_settings, apollo_inputs, functionality)
# Weight individuals
P <- apollo_weighting(P, apollo_inputs, functionality)
### Prepare and return outputs of function
P = apollo_prepareProb(P, apollo_inputs, functionality)
return(P)
}
# Estimate the model
# apollo_beta <- apollo_searchStart(apollo_beta, apollo_fixed,apollo_probabilities, apollo_inputs)
lcl_model <- apollo_estimate(apollo_beta, apollo_fixed, apollo_probabilities, apollo_inputs)
# Print results
apollo_modelOutput(lcl_model)
Apollo ignition sequence completed
All checks on apollo_control completed.
All checks on database completed.
[1] "Print value for 'apollo_inputs$n_classes':"
NULL
Error in 1:n : argument of length 0