Search code examples
rplot

Is there a way to create Wright Maps (item-person maps) in R using individual person labels in the visualization?


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:

an example item-person map

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

example R WrightMap output with person histogram

Is there a way to coerce the personHist argument into using labels rather than bars to represent the distribution of person theta values?


Solution

  • 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

    enter image description here