Multivariate model with many dependent variables

Hi all,

I’m building a multivariate model with many dependent variables (210), and I was wondering if there’s a way to specify them within mvbind() and set_prior() without having to list them all by name.

I tried different things, like creating a dv_names variable and directly indexing from the dataframe, but I can’t get anything to work. I get variations of the following error: Error: The following variables can neither be found in 'data' nor in 'data2': 'dv_names'

In case it’s needed, here’s a minimal example with 5 dependent variables:

library(tidyverse)
library(brms)

# Simulated dataset

set.seed(7890)

dat <- tibble(pID = rep(1:100, 5),
              DVs = rep(c('DV1', 'DV2', 'DV3', 'DV4', 'DV5'), 
                        each = 100),
              value = rep(runif(100, min=-1, max=1), 5),
              IV = rep(sample(1:12, 100, replace = TRUE), 5))

dat <- dat %>%
  pivot_wider(names_from = DVs, values_from = value)


# Model specification

formula = bf(mvbind(DV1, DV2, DV3, DV4, DV5) ~ 1 + IV) + set_rescor(FALSE)

priors = c(set_prior('normal(0, 0.5)', class = 'Intercept',
                   resp = c("DV1", "DV2", "DV3", "DV4", "DV5")),
         set_prior('normal(0, 0.1)', class = 'sigma',
                   resp = c("DV1", "DV2", "DV3", "DV4", "DV5")),
         set_prior('normal(0, 0.2)', class = 'b'))

b1 <- brm(formula = formula,
          data = dat, family = gaussian(),
          prior = priors,
          iter = 2000, warmup = 1000, cores = 4, chains = 4,
          seed = 7890)
summary(b1)

  • Operating System: macOS Big Sur
  • brms Version: 2.15.0

Not very experienced with brms so I appreciate all the help!
I’m looking forward to your suggestions.

Not sure about a clever brms solution, but an R hack that might save you some time would be something like

eval(parse(text = paste0("mvbind(", paste(paste0("DV", 1:210), collapse = ", "), ")")))

This generates your long, comma-separated list of variable names for you as a character string (assuming they follow some regular pattern), and then evaluates (?eval) that string as if it were R code (?parse).

1 Like

This worked like a charm, thanks a lot!

For future reference, this is the code I used (had to directly index DV column names from the dataframe dat, otherwise eval() wouldn’t recognise them as objects):

formula = eval(parse(text = paste0("bf(mvbind(", paste(paste0(names(dat)[1:210]), collapse = ", "), ") ~ 1 + IV)")))

For priors, just specifying a variable with DV column names works well.

dv_names <- names(dat)[1:210]

priors = c(
  set_prior('normal(0, 0.5)', class = 'Intercept',
         resp = dv_names),
  set_prior('normal(0, 0.1)', class = 'sigma',
         resp = dv_names))