Plotting Unidimensional/Dichotomous Models
Updated Fri 24-Apr-2020
Setup and basics
This is an introduction to the
wrightMap function in the
WrightMap package. The wrightMap function creates Wright Maps based on person estimates and item parameters produced by an item response analysis. The CQmodel function reads output files created using ConQuest software and creates a set of data frames for easy data manipulation, bundled in a CQmodel object. The wrightMap function can take a CQmodel object as input or it can be used to create Wright Maps directly from data frames of person and item parameters.
Let’s start by installing the latest version of the package from CRAN.
We will also install RColorBrewer to take advantage of its color palettes.
A simple dichotomous example
To plot a simple Rasch model, we start by creating mock person and item estimates.
For the person proficiencies we create a single vector with 1000 values.
# We set the seed to reproduce the same results set.seed(2020) rasch.sim.thetas <- rnorm(1000)
And for the item difficulties we create a vector with 10 values.
rasch.sim.thresholds <- runif(10, -3, 3)
We now have all we need to create a WrightMap with a single line.
wrightMap( rasch.sim.thetas, rasch.sim.thresholds)
We can start to customize the Wright Map by simply relabeling its main parts using
wrightMap(rasch.sim.thetas, rasch.sim.thresholds , main.title = "This is my example Wright Map" , axis.persons = "This is the person distribution" , axis.items = "This are my survey questions")
The Person Side and the Item Side
If you do not like histograms, Wright Map has the option
person.side that allows you to switch between histograms (the default option:
personHist ) or density using the option
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, person.side = personDens)
Or, you may want to change the way items are represented by using the option
item.side , which offers in addition to
itemModern (the default representation), it offers
itemClassic (for ConQuest-style Wright Maps), and a
itemHist for a histogram summary of the items.
itemClassic options is well suited for cases where you want to include many items using less space (or if you really like the original plain text flavored Wright Maps). See in this example how we are including 150 item difficulties.
rasch.sim.thresholds.2 <- runif(150, -3, 3) wrightMap(rasch.sim.thetas, rasch.sim.thresholds.2, item.side = itemClassic)
Alternatively, you can represent use a back-to-back histogram representation with
itemHist (notice that in the following example we are using the option
item.prop to adjust the relative sizes of the person and item side).
rasch.sim.thresholds.3 <- rnorm(150) wrightMap(rasch.sim.thetas, rasch.sim.thresholds.2, item.side = itemHist, item.prop = 0.5)
Customizing Wright Maps
Let us focus on the defaults item and person side representations to explore their potential customizations.
You might want to remove the label for the item difficulties by setting
show.thr.lab = FALSE.
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.lab = FALSE)
Or you might want to see just labels, by turning of symbols with
show.thr.sym = FALSE.
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.sym = FALSE)
Let’s start by making all the symbols bigger with
thr.sym.cex = 2.5 (default is 1).
wrightMap(rasch.sim.thetas, rasch.sim.thresholds , show.thr.lab = FALSE, thr.sym.cex = 2.5)
To select what kind of symbols you want to use you can use the
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.lab = FALSE , thr.sym.cex = 2.5, thr.sym.pch = 17)
For a list of all the characters that you can use in R and their code, you can type
?points or visit:
For the next couple of examples we will need some colors.
itemcolors <- brewer.pal(10, "Paired")
Now let’s use those colors in our item difficulty symbols using the
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.lab = FALSE , thr.sym.pch = 17, thr.sym.cex = 2.5, thr.sym.col.fg = itemcolors)
Notice that there is also a
thr.sym.col.bg parameter that controls the secondary color of symbols that have both foreground and background (i.e. the PCH’s from 21 to 25).
You’ll notice that our color vector has 10 colors, and we have 10 item difficulties. In the
wrightMap function, each item difficulty receives it’s color from the corresponding color vector. This means that you can control the properties of each one of the points separately. Let’s just change the color, symbol and size of the 2nd and 8th item difficulty by passing custom vectors to the
thr.sym.cex , and
itemcolors28 <- c("grey", "red", "grey", "grey", "grey", "grey", "grey", "red", "grey") itempch28 <- c(19, 18, 19, 19, 19, 19, 19, 18, 19) itemcex28 <- c(1, 2.5, 1, 1, 1, 1, 1, 2.5, 1) wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.lab = FALSE, thr.sym.pch = itempch28, thr.sym.cex = itemcex28, thr.sym.col.fg = itemcolors28)
But if you do not like symbols that much, you can stick to labeling the item difficulty parameters. However, we need some items names to make this more interesting.
itemnames <- c("Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Donner", "Blitzen", "Rudolph", "Olive")
With those ten names in a vector we can now assign them to our item difficulties using the
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.sym = FALSE , thr.lab.text = itemnames)
Just as we did with the symbols, we can can control the size of the text using the
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.sym = FALSE , thr.lab.text = itemnames, thr.lab.cex = 1.5)
And we can of course control the colors using
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.sym = FALSE , thr.lab.text = itemnames, thr.lab.col = itemcolors, thr.lab.cex = 1.5)
Finally, if you want to go crazy, you can also change the type style using
thr.lab.font. This parameter follows the R convention where 1 = plain, 2 = bold, 3 = italic, 4 = bold italic.
For this example, we are going to pass a vector of length 4 with each style.
wrightMap will deal with this by repeating it until it matches the number of item difficulties, 10 in this case, so it will produce the following vector:
wrightMap(rasch.sim.thetas, rasch.sim.thresholds, show.thr.sym = FALSE , thr.lab.text = itemnames, thr.lab.col = itemcolors , thr.lab.cex = 1.5, thr.lab.font = c(1:4))