Multidimensional Example

This example demonstrates how a multidimensional IRT test can be scored and modified for offline and on-line use. As well, it compares the effect of scoring the entire test given all possible responses to the use of a CAT scheme. The final section demonstrates how various elements in the GUI can be modified for more customized presentations.

The following code-block defines 100 items for a two factor math test measuring addition and multiplication.

library('mirtCAT')
options(stringsAsFactors = FALSE)

# define population IRT parameters
set.seed(1234)
nitems <- 120
itemnames <- paste0("Item.", 1:nitems)
a <- matrix(c(rlnorm(nitems/2, 0.2, 0.3), rnorm(nitems/4, 0, 0.3), numeric(nitems/2),
    rnorm(nitems/4, 0, 0.3), rlnorm(nitems/2, 0.2, 0.3)), nitems)
d <- matrix(rnorm(nitems))
pars <- data.frame(a, d)
colnames(pars) <- c("a1", "a2", "d")
trait_cov <- matrix(c(1, 0.5, 0.5, 1), 2, 2)

# create mirt_object
mod <- generate.mirt_object(pars, itemtype = "2PL", latent_covariance = trait_cov)

# math items definitions addition for one factor and multiplication for the other
questions <- answers <- character(nitems)
options <- matrix("", nitems, 5)
spacing <- floor(d - min(d)) + 1  #easier items have more variation

for (i in 1:nitems) {
    if (i < 31) {
        # addition
        n1 <- sample(1:100, 1)
        n2 <- sample(101:200, 1)
        ans <- n1 + n2
        questions[i] <- paste0(n1, " + ", n2, " = ?")
    } else if (i < 61) {
        # addition and multiplication
        n1 <- sample(1:50, 1)
        n2 <- sample(51:100, 1)
        m1 <- sample(1:10, 1)
        m2 <- sample(1:10, 1)
        ans <- n1 + n2 + m1 * m2
        questions[i] <- paste0(n1, " + ", n2, " + ", m1, " * ", m2, " = ?")
    } else if (i < 91) {
        # multiplication and addition
        n1 <- sample(1:10, 1)
        n2 <- sample(1:10, 1)
        m1 <- sample(1:25, 1)
        m2 <- sample(1:25, 1)
        ans <- n1 + n2 + m1 * m2
        questions[i] <- paste0(m1, " * ", m2, " + ", n1, " + ", n2, " = ?")
    } else {
        # multiplication
        m1 <- sample(1:50, 1)
        m2 <- sample(1:50, 1)
        ans <- n1 + n2 + m1 * m2
        questions[i] <- paste0(m1, " * ", m2, " = ?")
    }
    answers[i] <- as.character(ans)
    ch <- ans + sample(c(-5:-1, 1:5) * spacing[i, ], 5)
    ch[sample(1:5, 1)] <- ans
    options[i, ] <- as.character(ch)
}

# load list of items and their answers
df <- data.frame(Question = questions, Option = options, Answer = answers, Type = "radio")

Next, we generate a possible response pattern and pass it to the mirtCAT() function. The first run ensures that all items are used by choosing a very small standard error criteria.

set.seed(1)
pat <- generate_pattern(mo = mod, Theta = c(-0.5, 0.5), df = df)
head(pat)
## [1] "145" "195" "200" "232" "207" "175"
# Set min_SEM to be very small so every item is administered
result <- mirtCAT(df = df, mo = mod, local_pattern = pat, design = list(min_items = 120))
print(result)
##  n.items.answered    Theta_1   Theta_2 SE.Theta_1 SE.Theta_2
##               120 -0.3700413 0.3307952  0.2382641  0.1991176
# summary(result)
plot(result, scales = list(x = list(at = NULL)))

plot of chunk unnamed-chunk-2

MCATresult <- mirtCAT(df = df, mo = mod, criteria = "Drule", local_pattern = pat,
    start_item = "Drule", design = list(min_SEM = 0.4))
print(MCATresult)
##  n.items.answered    Theta_1   Theta_2 SE.Theta_1 SE.Theta_2
##                18 -0.5315824 0.7334699  0.3922312  0.3525484
summary(MCATresult)
## $final_estimates
##              Theta_1   Theta_2
## Estimates -0.5315824 0.7334699
## SEs        0.3922312 0.3525484
## 
## $raw_responses
##  [1] "3" "2" "1" "3" "3" "5" "5" "3" "1" "3" "3" "1" "1" "3" "4" "1" "5"
## [18] "4"
## 
## $scored_responses
##  [1] 1 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 1 0
## 
## $items_answered
##  [1]  40 118  59  65  41   3  93  31  87  63 107  24  96  82   5  15 110
## [18]  21
## 
## $thetas_history
##          Theta_1      Theta_2
##  [1,]  0.0000000  0.000000000
##  [2,]  0.3300105  0.279113446
##  [3,]  0.1417414 -0.280432565
##  [4,] -0.3095254 -0.381602239
##  [5,] -0.2671319 -0.118300124
##  [6,] -0.6102673 -0.162056668
##  [7,] -0.3903506 -0.144267073
##  [8,] -0.3774343  0.003104469
##  [9,] -0.5382694 -0.006176567
## [10,] -0.5065324  0.176070479
## [11,] -0.4950992  0.384450873
## [12,] -0.4864138  0.521754076
## [13,] -0.3538260  0.527263448
## [14,] -0.3480255  0.626719969
## [15,] -0.3465017  0.697101041
## [16,] -0.4941312  0.690762145
## [17,] -0.4398393  0.693085300
## [18,] -0.4374100  0.737414634
## [19,] -0.5315824  0.733469947
## 
## $thetas_SE_history
##         Theta_1   Theta_2
##  [1,] 1.0000000 1.0000000
##  [2,] 0.8676229 0.9072747
##  [3,] 0.8150130 0.5880721
##  [4,] 0.6409551 0.6047584
##  [5,] 0.6340877 0.4731552
##  [6,] 0.5635719 0.4760173
##  [7,] 0.4990944 0.4734596
##  [8,] 0.4982264 0.4252720
##  [9,] 0.4648866 0.4251890
## [10,] 0.4618842 0.3967178
## [11,] 0.4609951 0.3806421
## [12,] 0.4605137 0.3706389
## [13,] 0.4363272 0.3715648
## [14,] 0.4364367 0.3653976
## [15,] 0.4365725 0.3593208
## [16,] 0.4196257 0.3580613
## [17,] 0.4045024 0.3584702
## [18,] 0.4045165 0.3533521
## [19,] 0.3922312 0.3525484
plot(MCATresult)

plot of chunk unnamed-chunk-2