Last data update: 2014.03.03

R: Generate an adaptive or non-adaptive test HTML interface
mirtCATR Documentation

Generate an adaptive or non-adaptive test HTML interface

Description

Provides tools to generate an HTML interface for creating adaptive and non-adaptive educational and psychological tests using the shiny package. Suitable for applying unidimensional and multidimensional computerized adaptive tests using item response theory methodology. Test scoring is performed using the mirt package. However, if no scoring is required (i.e., a standard survey) then defining a mirt object may be omitted.

Usage

mirtCAT(df = NULL, mo = NULL, method = "MAP", criteria = "seq",
  start_item = 1, local_pattern = NULL, design_elements = FALSE,
  cl = NULL, design = list(), shinyGUI = list(), preCAT = list(), ...)

## S3 method for class 'mirtCAT'
print(x, ...)

## S3 method for class 'mirtCAT'
summary(object, sort = TRUE, ...)

## S3 method for class 'mirtCAT'
plot(x, pick_theta = NULL, SE = 1, main = NULL,
  par.strip.text = list(cex = 0.7), par.settings = list(strip.background =
  list(col = "#9ECAE1"), strip.border = list(col = "black")), ...)

Arguments

df

a data.frame or list object containing the character vector inputs required to generate GUI questions through shiny. If factors are supplied instead of character vectors then the inputs will be coerced using the as.character() function (set stringsAsFactors = FALSE when defining a data.frame to avoid this). Each row in the object corresponds to a unique item. The object supports the follow column name combinations as inputs to specify the type of response format, questions, options, answers, and stems:

Type

Indicates the type of response input to use from the shiny package. The supported types are: 'radio' for radio buttons (radioButtons), 'select' for a pull-down box for selecting inputs (selectInput), 'text' for requiring typed user input (textInput), 'checkbox' for allowing multiple responses to be checked off (checkboxGroupInput), 'slider' for generating slider inputs (sliderInput), or 'none' for presenting only an item stem with no selection options. Note that slider inputs require additional arguments to be passed; see ... instructions below).

Question

If df is a data.frame, a character vector containing all the questions or stems to be generated. If df is a list, then the commands must be suitable for output with shiny (e.g., Question <- list(h6('Item 1'), list(h6('Nested', h4(' item 2')))))

Option.#

Names pertaining to the possible response options for each item, where the # corresponds to the specific category. For instance, a test with 4 unique response options for each item would contain the columns (Option.1, Option.2, Option.3, Option.4). If, however, some items have fewer categories than others then NA's can be used for response options that do not apply.

Answer or Answer.#

(Optional) A character vector (or multiple character vectors) indicating the scoring key for items that have correct answer(s). If there is no correct answer for a question then a value of NA must be declared.

Stem

(Optional) a character vector of absolute or relative paths pointing external markdown (.md) or HTML (.html) files to be used as item stems. NAs are used if the item has no corresponding file.

...

In cases where 'slider' inputs are used instead only the Question input is required along with (at minimum) a min, max, and step column. In rows where the Type == 'slider' the column names will correspond to the input arguments to sliderInput. Other input column options such as step, round, pre, post, ticks, inline, placeholder, width, and size are also supported for the respective inputs.

mo

single group object defined by the mirt::mirt() function. This is required if the test is to be scored adaptively or non-adaptively, but not required for general questionnaires. The object can be constructed by using the generate.mirt_object function if population parameters are known or by including a calibrated model estimated from the mirt function with real data.

method

argument passed to mirt::fscores() for computing new scores in the CAT stage, with the addition of a 'fixed' input to keep the latent trait estimates fixed at the previous values. Default is 'MAP'

criteria

adaptive criteria used, default is to administer each item sequentially using criteria = 'seq'.

Possible inputs for unidimensional adaptive tests include: 'MI' for the maximum information, 'MEPV' for minimum expected posterior variance, 'MLWI' for maximum likelihood weighted information, 'MPWI' for maximum posterior weighted information, 'MEI' for maximum expected information, and 'IKLP' as well as 'IKL' for the integration based Kullback-Leibler criteria with and without the prior density weight, respectively, and their root-nitems administered weighted counter-parts, 'IKLn' and 'IKLPn'.

Possible inputs for multidimensional adaptive tests include: 'Drule' for the maximum determinant of the information matrix, 'Trule' for the maximum (potentially weighted) trace of the information matrix, 'Arule' for the minimum (potentially weighted) trace of the asymptotic covariance matrix, 'Erule' for the minimum value of the information matrix, and 'Wrule' for the weighted information criteria. For each of these rules, the posterior weight for the latent trait scores can also be included with the 'DPrule', 'TPrule', 'APrule', 'EPrule', and 'WPrule', respectively. As a safety precaution, if the selected criteria do not weight by the posterior (and therefore do not exist for extreme response styles) and less than 5 items have been administered then the method is temporarily switched to the posterior weighting until a variable response pattern is observed.

Applicable to both unidimensional and multidimensional tests are the 'KL' and 'KLn' for point-wise Kullback-Leibler divergence and point-wise Kullback-Leibler with a decreasing delta value (delta*sqrt(n), where n is the number of items previous answered), respectively. The delta criteria is defined in the design object

Non-adaptive methods applicable even when no mo is passed are: 'random' to randomly select items, and 'seq' for selecting items sequentially.

start_item

two possible inputs to determine the starting item are available. Passing a single number will indicate the specific item to be used as the start item; default is 1, which selects the first item in the defined test/survey. If a character string is passed then the item will be selected from one of the item selections criteria available (see the criteria argument)

local_pattern

a character/numeric matrix of response patterns used to run the CAT application without generating the GUI interface. This option requires complete response pattern(s) to be supplied. local_pattern is required to be numeric if no questions are supplied, and the responses must be within a valid range of the defined mo object. Otherwise, it must contain character values of plausible responses which corresponds to the answer key and/or options supplied in df

design_elements

logical; return an object containing the test, person, and design elements? Primarily this is to be used with the findNextItem function

cl

an object definition to be passed to the parallel package (see ?parallel::parLapply for details). If defined, and if nrow(local_pattern) > 1, then each row will be run in parallel to help decrease estimation times in simulation work

design

a list of design based control parameters for adaptive and non-adaptive tests. These can be

min_SEM

Default is rep(0.3, nfact); minimum standard error or measurement to be reached for the latent traits (thetas) before the test is stopped. If the test is multidimensional, either a single value or a vector of values may be supplied to provide SEM criteria values for each dimension

delta_thetas

Default is rep(0, nfact); stopping criteria based on the change in latent trait values (e.g., a change from theta = 1.5 to theta = 1.54 would stop the CAT if delta_thetas = 0.05). The default disables this stopping criteria

thetas.start

a numeric vector of starting values for the theta parameters. Default is rep(0, nfact)

min_items

minimum number of items that must be answered before the test is stopped. Default is 1

max_items

maximum number of items that can be answered. Default is the length of the item bank

quadpts

Number of quadrature points used per dimension for integration (if required). Default is identical to scheme in fscores

theta_range

upper and lower range for the theta integration grid. Used in conjunction with quadpts to generate an equally spaced quadrature grid. Default is c(-6,6)

weights

weights used when criteria == 'Wrule', but also will be applied for weighted trace functions in the T- and A-rules. The default weights the latent dimensions equally. Default is rep(1/nfact), nfact), where nfact is the number of test dimensions

KL_delta

interval range used when criteria = 'KL' or criteria = 'KLn'. Default is 0.1

content

an optional character vector indicating the type of content measured by an item. Must be supplied in conjunction with content_prop

content_prop

an optional named numeric vector indicating the distribution of item content proportions. A content vector must also be supplied to indicate the item content membership. For instance, if content contains three possible item content domains 'Addition', 'Subtraction', and 'Multiplication', and the test should contain approximately half multiplication and a quarter of both addition and subtraction, then a suitable input would be

content_prop = c('Addition'=0.25, 'Subtraction'=0.25, 'Multiplication'=.5)

Note that content_prop must sum to 1 in order to represent valid population proportions.

classify

a numeric vector indicating cut-off values for classification above or below some prior threshold. Default does not use the classification scheme

classify_CI

a numeric vector indicating the confident intervals used to classify individuals being above or below values in classify. Values must be between 0 and 1 (e.g., 0.95 gives 95% confidence interval)

exposure

a numeric vector specifying the amount of exposure control to apply for each successive item (length must equal the number of items). The default uses no exposure control. If the item exposure is greater than 1 then the n most optimal criteria will be randomly sampled from. For instance, if exposure[5] == 3, and critiera = 'MI', then when the fifth item is to be selected from the remaining pool of items the top 3 candidate items demonstrating the largest information criteria will be sampled from. Naturally, the first and last elements of exposure are ignored since exposure control will be meaningless.

If all elements in exposure are between 0 and 1 then the Sympson-Hetter exposure control method will be implemented. In this method, an item is administered only if it passes a probability simulation experiment, otherwise it is removed from the item pool. Values closer to 1 are more likely to appear in the test, while value closer to 0 are more likely to be randomly discarded.

constraints

A named list declaring various item selection contraints for which particular item, where each list element is a vector of item numbers. Unless otherwise stated, multiple elements can be decalared (e.g., list(ordered = c(1:5), ordered = c(7:9)) is perfectly acceptable). These include:

not_scored

declaring items that can be selected but will not be used in the scoring of the CAT. This is primarily useful when including experimental items for future CATs. Only one vector of not_scored elements can be supplied

excluded

items which should not actually appear in the session (useful when re-testing participants who have already seen some of the items). Only one vector of excluded elements can be supplied

independent

declaring which items should never appear in the same CAT session. Use this if, for example, item 1 and item 10 have very similar questions types and therefore should not appear within the same session

ordered

if one item is selected during the CAT, administer this particular group of items in order according to the specified sequence

unordered

same as ordered, except the items in the group will be selected at random until the group is complete

customNextItem

a more advanced function of the form customNextItem <- function(design, person, test) to use a customized item selection method. This requires more complex programming and understanding of mirtCATs internal elements, and it's recommended to initially use a browser to understand the state of the input arguments.

Use this if you wish to program your item selection techniques explicitly, though this can be combined the internal findNextItem function with analogous inputs. Function must return a single integer value indicating the next item to administer or an NA value to indicate that the test should be terminated.

shinyGUI

a list of GUI based parameters to be over-written. These can be

title

A character string for the test title. Default is 'mirtCAT'

authors

A character string for the author names. Default is 'Author of survey'. If the input is an empty string ('') then the author information will be omitted in the GUI

instructions

A three part character vector indicating how to use the GUI. Default is:

c("Instructions:", 
       "To progress through the interface, click on the action button below.",
       "Next")
firstpage

The first page of the shiny GUI. Default prints the title and information message.

 
         list(h1('Welcome to the mirtCAT interface'),
              The following interface was created using the mirtCAT package. 
              To cite the package use citation('mirtCATd') in R.')
         

If an empty list is passed, this page will be skipped.

begin_message

Text to display on the page prior to beginning the CAT. Default is "Click the action button to begin."

demographics

A person information page used in the GUI for collecting demographic information, generated using tools from the shiny package. For example, the following code asks the participants about their Gender:

 
         list(selectInput(inputId = 'gender',
                  label = 'Please select your gender.',
                  choices = c('', 'Male', 'Female', 'Other'),
                  selected = ''))
        

By default, the demographics page is not included.

demographics_inputIDs

a character vector required if a custom demographics input is used. Default is demographics_inputIDs = 'gender', corresponding to the demographics default

max_time

maximum time allowed for the generated GUI, measured in seconds. For instance, if the test should stop after 10 minutes then the number 600 should be passed (10 * 60). Default is Inf, therefore no time limit

temp_file

a character vector indicating where a temporary .rds file containing the response information should be saved while the GUI is running. The object will be saved after each item is successfully completed. This is used to save response information to the hard drive in case there are power outages or unexpected computer restarts.

If NULL, no temp file will be created. Upon completion of the test, the temp file will be deleted. If a file already exists, however, then this will be used to resume the GUI at the last location where the session was interrupted

lastpage

A function printing the last message, indicating that the test has been completed (i.e., criteria has been met). The function requires exactly one argument (called person), where the input argument is the person object that has been updated throughout the test. The default function is

function(person){ 
                    return(list(h5("You have successfully completed the interface. 
                                   Click the action button to terminate the application.")))
                     } 
css

a character string defining CSS elements to modify the GUI presentation elements. The input string is passed to the argument tags$style(HTML(shinyGUI$css)) prior to constructing the user interface

forced_choice

logical; require a response to each item? Default is TRUE. This should only be set to FALSE for surveys (not CATs)

stopApp

logical; use a stopApp() call after the interface has been completed? Default is TRUE. However, when hosting an application on a remote server this should be set to FALSE to allow a more graceful completion (in which case the last page will be displayed until the browser tab is closed)

ui

a shiny UI function used to define the interface. If NULL, the default one will be used. See mirtCAT:::default_UI for the internal code definition

preCAT

a list object which can be used to specify a pre-CAT block in which different test properties may be applied prior to beginning the CAT session. If the list is empty, no preCAT block will be used. All of the following elements are required to use the preCAT input:

min_items

minimum number of items to administer before the CAT session begins. Default is 0

max_items

max number of items to administer before the CAT session begins. An input greater than 0 is required to run the preCAT stage

criteria

selection criteria (see above). Default is 'random'

method

estimation criteria (see above). It is generally recommended to select a method which can deal with all-or-none response patterns, such as 'EAP' or 'MAP', or in the multidimensional case 'DPrule' or 'TPrule'. Default is 'MAP'

response_variance

logical; terminate the preCAT stage when there is variability in the response pattern (i.e., when maximum-likelihood estimation contains a potential optimum)? Default is FALSE

...

additional arguments to be passed to mirt, fscores, runApp, or lattice

x

object of class 'mirtCAT'

object

object of class 'mirtCAT'

sort

logical; sort the response patterns based on the order they were administered? If FALSE, the raw response patterns containing NAs will be returned for items that were not administered

pick_theta

a number indicating which theta to plot (only applicable for multidimensional tests). The default is to facet each theta on one plot, but to plot only the first factor pass pick_theta = 1

SE

size of the standard errors to plot. The default is 1, and therefore plots the standard error. To obtain the 95% interval use SE = 1.96 (from the z-distribution)

main

title of the plot. Will default to 'CAT Standard Errors' or 'CAT ##% Confidence Intervals' depending on the SE input

par.strip.text

plotting argument passed to lattice

par.settings

plotting argument passed to lattice

Details

All tests will stop once the 'min_SEM' criteria has been reached or classification above or below the specified cutoffs can be made. If all questions should be answered, users should specify an extremely small 'min_SEM' or, equivalently, a large 'min_items' criteria to the design list input.

Value

Returns a list object of class 'Person' containing the following elements:

raw_responses

A character vector indicating the raws responses to the respective items, where NA indicates the item was not answered

scored_responses

An integer vector of scored responses if the item_answers input was used for each respective item

items_answered

An integer vector indicating the order in which the items were answered

thetas

A numeric vector indicating the final theta estimates

SE_thetas

A numeric vector indicating the standard errors of the final theta estimates

thetas_history

A matrix indicating the progression of updating the theta values during the test

thetas_SE_history

A matrix indicating the standard errors for theta after each successive item was answered

item_time

A numeric vector indicating how long the respondent took to answer each question (in seconds)

demographics

A data.frame object containing the information collected on the first page of the shiny GUI. This is used to store the demographic information for each participant

classification

A character vector indicating whether the traits could be classified as 'above' or 'below' the desired cutoffs

HTML help files, exercises, and examples

To access examples, vignettes, and exercise files that have been generated with knitr please visit https://github.com/philchalmers/mirtCAT/wiki.

Author(s)

Phil Chalmers rphilip.chalmers@gmail.com

See Also

generate_pattern, generate.mirt_object

Examples

## Not run: 

### unidimensional scored example with generated items

# create mo from estimated parameters
set.seed(1234)
nitems <- 50
itemnames <- paste0('Item.', 1:nitems)
a <- matrix(rlnorm(nitems, .2, .3))
d <- matrix(rnorm(nitems))
dat <- simdata(a, d, 1000, itemtype = 'dich')
mod <- mirt(dat, 1)
coef(mod, simplify=TRUE)

# alternatively, define mo from population values (not run)
pars <- data.frame(a1=a, d=d)
mod2 <- generate.mirt_object(pars, itemtype='2PL')
coef(mod2, simplify=TRUE)

# simple math items
questions <- answers <- character(nitems)
choices <- matrix(NA, nitems, 5)
spacing <- floor(d - min(d)) + 1 #easier items have more variation in the options

for(i in 1:nitems){
    n1 <- sample(1:50, 1)
    n2 <- sample(51:100, 1)
    ans <- n1 + n2
    questions[i] <- paste0(n1, ' + ', n2, ' = ?')
    answers[i] <- as.character(ans)
    ch <- ans + sample(c(-5:-1, 1:5) * spacing[i,], 5)
    ch[sample(1:5, 1)] <- ans
    choices[i, ] <- as.character(ch)
}

df <- data.frame(Question=questions, Option=choices, 
                              Type = 'radio', stringsAsFactors = FALSE)
head(df)

(res <- mirtCAT(df)) #collect response only (no scoring or estimating thetas)
summary(res)

# include scoring by providing Answer key
df$Answer <- answers
(res_seq <- mirtCAT(df, mod)) #sequential scoring 
(res_random <- mirtCAT(df, mod, criteria = 'random')) #random
(res_MI <- mirtCAT(df, mod, criteria = 'MI', start_item = 'MI')) #adaptive, MI starting item

summary(res_seq)
summary(res_random)
summary(res_MI)

#-----------------------------------------

# run locally, random response pattern given Theta
set.seed(1)
pat <- generate_pattern(mod, Theta = 0, df=df)
head(pat)

# seq scoring with character pattern for the entire test (adjust min_items)
res <- mirtCAT(df, mod, local_pattern=pat, design = list(min_items = 50)) 
summary(res)

# same as above, but using special input vector that doesn't require df input
set.seed(1)
pat2 <- generate_pattern(mod, Theta = 0)
head(pat2)
print(mirtCAT(mo=mod, local_pattern=pat2))

# run CAT, and save results to object called person (start at 10th item)
person <- mirtCAT(df, mod, item_answers = answers, criteria = 'MI', 
                  start_item = 10, local_pattern = pat)
print(person)
summary(person)

# plot the session
plot(person) #standard errors
plot(person, SE=1.96) #95 percent confidence intervals

#-----------------------------------------

### save response object to temp directory in case session ends early
wdf <- paste0(getwd(), '/temp_file.rds')
res <- mirtCAT(df, mod, shinyGUI = list(temp_file = wdf))

# resume test this way if test was stopped early (and temp files were saved)
res <- mirtCAT(df, mod, shinyGUI = list(temp_file = wdf))
print(res)


## End(Not run)

Results