Page 1 of 1

truncated normal for random parameters

Posted: 06 Mar 2026, 09:38
by bbiondi
Dear all,

I need to estimate a model with random parameters, imposing a strictly negative or positive distribution for the parameters. I have tried with the negative log-normal distribution in the mixed logit specification, but it has too heavy tail and produces unrealistic marginal rates of substitution. I would like to impose a truncated normal below zero (and I also need a truncated normal above zero for a different parameter). I found a couple of questions in the forum related to this topic, but the issue was not solved.

Below is my code, which now includes normally distributed parameters. I need always negative parameters for ild, diarrea, alop and nausea (they are adverse effects), and always positive coefficient for fs (it represents the efficacy of the treatment); thanks for any help:

Code: Select all

### Vector of parameters, including any that are kept fixed in estimation
apollo_beta=c(fs_mu      = 0,
              fs_sigma      = 0,
              diarrea_mu = 0,
              diarrea_sigma = 0,
              alop_mu    = 0,
              alop_sigma    = 0,
              nausea_mu  = 0,
              nausea_sigma  = 0,
              ild_mu     = 0,
              ild_sigma     = 0
)

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

apollo_draws = list(
  interDrawsType = "halton",
  interNDraws = 500,
  interUnifDraws = c(),
  interNormDraws = c("draws_fs","draws_alop","draws_nausea","draws_diarrea","draws_ild")
)

apollo_randCoeff = function(apollo_beta, apollo_inputs){
  randcoeff = list()
  # NORMAL
  randcoeff[["fs"]] = fs_mu + fs_sigma * draws_fs 
  randcoeff[["diarrea"]] =  diarrea_mu + diarrea_sigma * draws_diarrea 
  randcoeff[["alop"]] = alop_mu + alop_sigma * draws_alop 
  randcoeff[["nausea"]] =  nausea_mu + nausea_sigma * draws_nausea 

  return(randcoeff)
}

# ################################################################# #
#### 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()
  
  ### List of utilities: these must use the same names as in mnl_settings, order is irrelevant
  V = list()
  V[["A"]]  = fs*fs_A + diarrea * diarrea_A + alop*alopecia_A + nausea*nausea_A + ild *ild_A
  V[["B"]]  = fs*fs_B + diarrea * diarrea_B + alop*alopecia_B + nausea*nausea_B + ild *ild_B 
  
  ### Define settings for MNL model component
  mnl_settings = list(
    alternatives  = c(A=1, B=2), 
    #avail         = list(), 
    choiceVar     = choice,
    utilities     = 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)
  ### Media sui draw inter-individuali
  P = apollo_avgInterDraws(P, apollo_inputs, functionality)
  
  ### Prepare and return outputs of function
  P = apollo_prepareProb(P, apollo_inputs, functionality)
  return(P)
}

Re: truncated normal for random parameters

Posted: 09 Mar 2026, 18:25
by stephanehess
Hi

truncated normal would not allow you to calculate WTP. How about log-uniform, which is an exponential of uniform. Shorter tails than Lognormal

Stephane