Using WrightMap with the TAM Package

Author

David Torres Irribarra & Rebecca Freund

Published

September 25, 2024

Introduction

WrightMap features close integration with Conquest, allowing you to easily read from its output files. However, this is just a nice convenience for Conquest users, as WrightMap was designed to create beautiful item-person plots simply reading standard R matrices; all you need is a matrix of item parameters and a matrix of person estimates, and you can start creating nice Wright Maps. For this reason, the WrightMap package can be used to plot the results of any IRT software and makes it very easy to integrate with other R packages that estimate IRT models.

This post will show you how you can integrate R with one of these estimation packages, the Test Analysis Module (TAM) package, in just a couple of lines.

Setup

Let’s start by loading TAM.

library(TAM)
Loading required package: CDM
Loading required package: mvtnorm
**********************************
** CDM 8.2-6 (2022-08-25 15:43:23)       
** Cognitive Diagnostic Models  **
**********************************
* TAM 4.2-21 (2024-02-19 18:52:08)

And we can use one of TAM’s simulated datasets (without any missing data in this case) for this example:

data(data.sim.rasch)
str(data.sim.rasch)
 num [1:2000, 1:40] 1 0 1 1 1 1 1 1 1 1 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:40] "I1" "I2" "I3" "I4" ...

A quick look with str confirms that we now have a simulated dataset with responses from 2000 persons (rows) to 40 items (columns). We are ready to go!

Analysis with TAM

In this example, we will run a Rasch model using the TAM command tam.mml, which will estimate the model using a marginal maximum likelihood method.

mod1 <- tam.mml(resp=data.sim.rasch, verbose=FALSE)

The estimation should take very little time, and you should see a summary of the results and the total time it took to run the analysis.

Person Estimates

You can get person estimates in several ways in TAM, but for this example, I will use the tam.wle command, which produces Warm Likelihood Estimates (WLE) for each respondent.

persons.mod1 <- tam.wle(mod1)
Iteration in WLE/MLE estimation  1   | Maximal change  0.8281 
Iteration in WLE/MLE estimation  2   | Maximal change  0.4335 
Iteration in WLE/MLE estimation  3   | Maximal change  0.0883 
Iteration in WLE/MLE estimation  4   | Maximal change  7e-04 
Iteration in WLE/MLE estimation  5   | Maximal change  0 
----
 WLE Reliability= 0.894 
str(persons.mod1)
Classes 'tam.wle' and 'data.frame': 2000 obs. of  7 variables:
 $ pid         : int  1 2 3 4 5 6 7 8 9 10 ...
 $ N.items     : num  40 40 40 40 40 40 40 40 40 40 ...
 $ PersonScores: num  19 14 35 14 27 12 23 17 5 12 ...
 $ PersonMax   : num  40 40 40 40 40 40 40 40 40 40 ...
 $ theta       : num  -0.116 -0.791 2.373 -0.791 0.964 ...
 $ error       : num  0.366 0.377 0.498 0.377 0.382 ...
 $ WLE.rel     : num  0.894 0.894 0.894 0.894 0.894 ...
 - attr(*, "ndim")= int 1
 - attr(*, "nobs")= int 2000
 - attr(*, "M_sq_error")= Named num 0.165
  ..- attr(*, "names")= chr "Dim1"
 - attr(*, "WLEvar")= Named num 1.55
  ..- attr(*, "names")= chr "Dim1"
 - attr(*, "WLEM")= Named num 0.000865
  ..- attr(*, "names")= chr "Dim1"
 - attr(*, "WLE.rel")= num 0.894
 - attr(*, "call")= language tam.wle(tamobj = mod1)

If we look at the resulting matrix, we can see that we have several columns, including:

  • pid: the ID of the respondent
  • N.items: the number of items
  • PersonScores: The score of each person
  • PersonMax: The maximum possible score of each person
  • theta: The WLE estimate
  • error: The standard error of the WLE estimate
  • WLE.rel: The WLE reliability

You can look at the TAM documentation for more details, but for this example, we want to focus on the theta column, which contains the person estimates we need to create our Wright map.

We can get the data we need by selecting just that column:

WLEestimates.mod1 <- persons.mod1$theta

Item Parameters

And we can get our item estimates using the tam.threshold command.

thresholds.mod1 <- tam.threshold(mod1)

Creating the Wright Map

With these two matrices, we are ready to plot our Wright Map:

wrightMap(WLEestimates.mod1, thresholds.mod1)

And you can start editing it to make it nicer:

wrightMap(WLEestimates.mod1, thresholds.mod1, show.thr.lab = FALSE, label.items = c(1:40), label.items.rows = 3)