In the past I have used WinSteps for the creation of item-person maps for IRT projects. I found the option to represent individual persons with a variable label particularly useful. Below is an example of what I mean:
Here the items (44b,44a,42b,45b,45c) and persons (TD, RSK, SD) are represented by character labels at their respective Beta and Theta levels on the trait scale. In this example, the person labels represent diagnostic groups. This is helpful for visualizing which items are measuring which groups in the person distribution.
Is there any way to create this type of map in R?
So far I have only been able to find resources for producing person histograms and density plots using the WrightMap function shown below
Is there a way to coerce the personHist argument into using labels rather than bars to represent the distribution of person theta values?
Yes, it is possible. The wrightMap
method from the WrightMap package offers customizable item- and person-side plots. However, you'll need some work to do to get a nice looking plot.
If we study the implementation of the method, we find that the person-side plot is generated via a call to
do.call(person.side, c(person.params, dots))
whereas person.side
is a plotting function (by default that is personHist
-- for greater detail cf. to the manual page for personHist
) and the person.params
objects is a list of arguments which is set as
person.params <- list(thetas = thetas, yRange = yRange, close.on.close = FALSE,
oma = c(0, 0, 0, 0), axis.logits = "", show.axis.logits = FALSE)
The thetas
object from this list is the same as the input object. Noteably, the object keeps its names during the computations. We can use that to construct out person side plot. Using example data adapted from the packages manual
set.seed(20231020)
library(WrightMap)
uni.proficiency <- rnorm(10, mean = -0.5, sd = 1)
uni.proficiency <- setNames(uni.proficiency, paste0("id", sprintf("%03i", 1:length(uni.proficiency))))
difficulties <- sort( rnorm( 20))
We can e.g. define
my_person.side <- function(thetas, yRange, oma, ...) {
r <- hist(thetas, breaks = "FD", plot = FALSE)
y <- cut(thetas, breaks = r$breaks, labels = r$mids)
x <- numeric(length = length(y))
text <- names(thetas)
for(bb in levels(y)) {# bb <- levels(y)[1]
x[y == bb] <- 0:(-c(table(y)[bb]) + 1)
}
par(oma = oma)
plot(x, y, type = "n", xlab = "", ylab = "",
ylim = yRange, xlim = c(min(x) - 0.5, 0), cex.lab = 0.8,
font.lab = 3)
text(x = x, y = as.numeric(as.character(y)), labels = text, cex = .7)
}
And a call to
wrightMap(uni.proficiency, difficulties, person.side = my_person.side)
gives