I am relatively new to IRT and brms
, so please forgive any errors or misunderstandings in my model.
I am trying to fit a multidimensional model in brms
using the cumulative family with a logit link. My data come from the German Socioeconomic Panel (SOEP), and I have selected 14 items for the model.
The challenge is that the SOEP questions have varying numbers of response categories (ranging from 3 to 7 in the items I am using). It appears that brms
requires a consistent scale across all items, but I prefer not to reduce, for example, a 7-category Likert scale to 3 categories.
Is there a way to accommodate varying response scales among items in brms
? Based on conversations here and here, it looks like it is possible in Stan, but I have not had any success in brms
.
For reference, the code below demonstrates what I would like to do using 9 generated items with 3 different scales (3-category, 5, and 7) distributed among 3 dimensions. I am using brms
version 2.20.4 on Windows.
####################### sample data
id <- 500
# creating a data frame with respondents, items, and dimensions
d <- data.frame(
id = rep(1:id, each = 9),
item = rep(1:9, id),
dim = rep(rep(1:3, each = 3), id)
)
# generating integer y values based on item
y <- function(item) {
switch(as.character(item),
"1" = sample(1:3, 1),
"2" = sample(1:5, 1),
"3" = sample(1:7, 1),
"4" = sample(1:3, 1),
"5" = sample(1:5, 1),
"6" = sample(1:7, 1),
"7" = sample(1:3, 1),
"8" = sample(1:5, 1),
"9" = sample(1:7, 1)
)
}
d$y <- sapply(d$item, y)
head(d, 20)
length(unique(d$id))
nrow(d)
#########################################
formula <- bf(
y ~ 1 + (1 |i| item) + (0 + dim | id), disc ~ 1 + (1 |i| item))
prior <-
prior("lkj(1)", class = "cor") +
prior("student_t(3, 0, 2.5)", class = "Intercept") +
prior("student_t(3, 0, 2.5)", class = "sd") +
prior("normal(0, 1)", class = "Intercept", dpar = "disc")
fit1 <- brm(
formula = formula,
data = d,
family = brmsfamily("cumulative", "logit", threshold = "flexible"),
prior = prior,
chains = 4,
iter = 2000,
warmup = 1000,
thin = 2,
control = list(adapt_delta = 0.99),
cores = parallel::detectCores()
)