knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(meow)
Item selection functions, as you may have guessed, implement the rules that determine which item is administered next to each respondent. They are one of the three core swappable components of a meow simulation. For the full module contract, see vignette("extending-meow"); this vignette focuses on the bundled selectors and how to write your own.
Every item selection function has the signature
select_fun <- function(pers, item, R, admin, adj_mat, ...) { # ... decide which items to administer ... return(admin) }
Any select_fun() receives the current person parameter estimates (pers), item parameter estimates (item), the full respondent-by-item response matrix (R), the integer administration matrix (admin), and the item co-exposure matrix (adj_mat). It then returns an administration matrix with the newly chosen cells marked with a non-zero integer value. The simulation harness itself will correctly record the order of administration, so you only need to mark newly administered items with non-zero values.
The default behavior when early stopping rules are not implemented in selection functions is run the simulation until it has administered every item to every respondent. The unadministered items for respondent i can be retrieved using which(admin[i, ] == 0), and the respondents who still have items to respond to can be found using which(rowSums(admin == 0) > 0).
select_sequential() administers the lowest-numbered remaining item to each
respondent, producing a fixed linear form.
select_sequential <- function(pers, item, R, admin, adj_mat = NULL) { if (!any(admin != 0)) { admin[, seq_len(min(5, ncol(admin)))] <- 1L # seed the first five items return(admin) } unadmin <- admin == 0 has <- which(rowSums(unadmin) > 0) nextcol <- max.col(unadmin[has, , drop = FALSE] + 0, ties.method = "first") admin[cbind(has, nextcol)] <- 1L admin }
select_random() draws one remaining item per respondent at random. It accepts a
select_seed for reproducibility, which it clears after use.
select_max_info() administers the remaining item with the greatest 2PL Fisher
information, $I(\theta) = a^2 P(\theta)(1 - P(\theta))$, evaluated at each
respondent's current ability estimate. The information for every
respondent-by-item combination is computed as a single matrix, and the maximum is
taken per row.
select_max_dist() and select_max_dist_enhanced() treat the item pool as a
network whose edge weights are derived from the co-exposure adjacency matrix adj_mat. They administer the item farthest (by shortest-path distance) from the items a respondent has already seen, breaking ties using maximum information. See vignette("network-item-selection").
A custom selector need only follow the prescribed function signature and return an updated admin matrix. Here we administer the item whose difficulty is closest to a respondent's current ability, which can be seen as maximizing information when all items are assumed to be equally discriminating.
select_targeted <- function(pers, item, R, admin, adj_mat = NULL) { if (!any(admin != 0)) { admin[, seq_len(min(5, ncol(admin)))] <- 1L return(admin) } for (i in which(rowSums(admin == 0) > 0)) { remaining <- which(admin[i, ] == 0) gap <- abs(item$b[remaining] - pers$theta[i]) admin[i, remaining[which.min(gap)]] <- 1L } admin }
Use it in a simulation by passing it as select_fun:
sim <- meow( select_fun = select_targeted, update_fun = update_theta_mle, data_loader = data_simple_1pl, data_args = list(N_persons = 50, N_items = 30), fix = "item" ) nrow(sim$results)
if (!any(admin != 0)) to seed an initial
set of items so that you have baseline parameter estimates to start from.admin unchanged when you want to end the simulation.meow_long() only when long data is genuinely more convenient.Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.