rshinybrms

Passing multiple user-selected coefficient variables to brms via R shiny?


I am creating an R Shiny web-app that would allow users to input a custom dataset, select analysis variables, and fit a Bayesian ANCOVA model using user-specified prior values. This is what the relevant code looks like: (server portion)


  bfit <- eventReactive(
    input$activate,
    ignoreNULL = F,
    {
      req(lmmformula, anovaformula, ancovaformula, input$interceptMean,
          input$interceptVariance, input$baselineMean, input$baselineVariance,
          input$treatmentMean, input$treatmentVariance, input$sigmaScale,
          input$seed)
      
      stanparams <- stanvar(input$interceptMean, "intercept_mean") +
        stanvar(sqrt(input$interceptVariance), "intercept_sd") +
        stanvar(input$baselineMean, "baseline_mean") + 
        stanvar(sqrt(input$baselineVariance), "baseline_sd") + 
        stanvar(input$treatmentMean, "treatment_mean") + 
        stanvar(sqrt(input$treatmentVariance), "treatment_sd") + 
        stanvar(input$sigmaScale, "sigma_scale")
      
      priors <- c(prior(normal(intercept_mean,
                               intercept_sd),
                        class = "Intercept"),
                  prior(normal(baseline_mean,
                               baseline_sd),
                        class = "b",
                        coef = input$baseline),
                  prior(normal(treatment_mean,
                               treatment_sd),
                        class = "b",
                        coef = input$group),
                  prior(cauchy(0, sigma_scale),
                        class = "sigma"))
      
      list(
        bayes = brm(ancovaformula(), data = sel_data(), silent = 1,
                    thin = 1, iter = input$iter, warmup = (input$iter/2),
                    prior = priors, stanvars = stanparams, seed = input$seed),
        
        bayesx2 = brm(ancovaformula(), data = sel_data(), silent = 1,
                      thin = 1, iter = (input$iter)*2, warmup = input$iter,
                      prior = priors, stanvars = stanparams, seed = input$seed)
      )
    }
  )
  
  observeEvent(input$activate, {
    bfit()
  })

When this is run using the taskButton input$activate, however, it throws this error:

Warning: Error in : The following priors do not correspond to any model parameter: 
b_input$baseline ~ normal(baseline_mean, baseline_sd)
b_input$group ~ normal(treatment_mean, treatment_sd)
Function 'default_prior' might be helpful to you.

Which suggests to me that, instead of interpreting the value of coef as that which is stored in the input$baseline variable, it reads in 'input$baseline' verbatim as the coefficient name.

How do I make it read the content of the variable instead, such that it interprets coef = input$baseline as the name of the coefficient stored in input$baseline, e.g. coef = measurement_1 ?

Edit: The ancovaformula variable is defined as:

ancovaformula <- reactive({
    req(sel_data(), longdata())
    ancovaformula = as.formula(paste(input$fwup, " ~ ", input$baseline,
                                     " + ", input$group))
  })

In which the inputs are character strings containing variable names, such that the final product, given values post, pre, and Tx, is:

post ~ pre + Tx

Solution

  • I managed to fix my issue using prior_string as follows:

      bfit <- eventReactive(
        input$activate,
        ignoreNULL = F,
        {
          req(lmmformula, anovaformula, ancovaformula)
          
          validate(
            need(input$upload != "", "Please upload a dataset in .xls or .xlsx
                  format"),
            need(input$interceptMean != "", "Please enter mean of model intercept
                 prior"),
            need(input$interceptVariance != "", "Please enter variance of model
                 intercept prior"),
            need(input$baselineMean != "", "Please enter mean of baseline effect 
                 prior"),
            need(input$baselineVariance != "", "Please enter variance of baseline
                 effect prior"),
            need(input$treatmentMean != "", "Please enter mean of treatment effect
                 prior"),
            need(input$treatmentVariance != "", "Please enter variance of treatment
                 effect prior"),
            need(input$sigmaScale != "", "Please enter scale of SD of outcome 
                 prior"),
            need(input$seed != "", "Please enter a seed for MCMC sampling")
          )
          
          stanparams <- stanvar(input$interceptMean, "intercept_mean") +
            stanvar(sqrt(input$interceptVariance), "intercept_sd") +
            stanvar(input$sigmaScale, "sigma_scale")
          
          priors <- c(prior(normal(intercept_mean,
                                   intercept_sd),
                            class = "Intercept"),
                      prior_string(paste0("normal(", input$baselineMean, ", ",
                                          sqrt(input$baselineVariance), ")"),
                            class = "b",
                            paste0(input$baseline)),
                      prior_string(paste0("normal(", input$treatmentMean, ", ",
                                   sqrt(input$treatmentVariance), ")"),
                            class = "b",
                            paste0(input$group)),
                      prior(cauchy(0, sigma_scale),
                            class = "sigma"))
          
          list(
            bayes = brm(ancovaformula(), data = sel_data(), silent = 1,
                        thin = 1, iter = input$iter, warmup = (input$iter/2),
                        prior = priors, stanvars = stanparams, seed = input$seed),
            
            bayesx2 = brm(ancovaformula(), data = sel_data(), silent = 1,
                          thin = 1, iter = (input$iter)*2, warmup = input$iter,
                          prior = priors, stanvars = stanparams, seed = input$seed)
          )
        }
      )
      
      observeEvent(input$activate, {
        bfit()
      })