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)))
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)