D3MIRT
ModelingThe D3mirt
analysis is based on descriptive
multidimensional item response theory (DMIRT; Reckase, 2009, 1985;
Reckase & McKinley, 1991) and can be used to analyze dichotomous and
polytomous items (see Muraki & Carlson, 1995) in a three-dimensional
ability space. The method is foremost visual and illustrates item
characteristics with the help of vector geometry in which items are
represented by vector arrows.
In DMIRT analysis, also called within multidimensional modeling, it is assumed that items in a multidimensional ability space can measure single or multiple latent traits (Reckase, 2009, 1985; Reckase & McKinley, 1991). The methodology is a type of data reduction technique based on the compensatory model (Reckase, 2009), i.e., a type of measurement model that uses linear combinations of \(\theta\)-values for ability assessment. The method seeks to maximize item discrimination and so is descriptive because the results describe the extent to which items in a test are unidimensional, i.e., that the items discriminate on one dimension only, or are within-multidimensional, i.e., that the items discriminate on more than one dimension.
Regarding vector orientation, the angle of the vector arrows indicates what traits, located along the orthogonal axes in the model, an item can be said to describe (Reckase, 2009, 1985, Reckase & McKinley, 1991). For instance, in a two-dimensional space, an item is unidimensional if its item vector arrow is at \(0°\) with respect to one of the axes in the model, and \(90°\) with respect to the other. Such an item describes a singular trait only. In contrast, an item is within-multidimensional if its item vector arrow is oriented at \(45°\) in relation to the axes in the model. Such an item describes both traits in the model equally well. The same criteria are extended to the three-dimensional case.
The DMIRT approach uses two types of item models, dependent on item
type. If dichotomous items are used, the analysis is based on the
two-parameter logistic model (M2PL). If polytomous items are used, the
analysis is extended to the two-parameter graded response model (MGRM;
Muraki & Carlson, 1995). In both cases, the estimation process
consists of first fitting a compensatory multidimensional two-parameter
model so that discrimination and difficulty (\(a\) and \(d\)) parameters can be extracted. For
D3mirt
, this implies that a compensatory three-dimensional
M2PL or MGRM must be fitted. Next, using these parameters the DMIRT
computation finds the direction of the highest possible discrimination
slope for each item. The direction, in turn, shows what latent trait the
item can be said to measure in the multidimensional latent model. The
output is visualized as vector arrows representing item response
functions located in a multidimensional space pointing in the direction
of the maximum slope.
The most central estimates, briefly explained below, in DMIRT analysis are the single multidimensional discrimination (\(MDISC\)) parameter, the multidimensional difficulty (\(MDIFF\)) parameters, and the directional discrimination (\(DDISC\)) parameters (Reckase2009, 1985; Reckase & McKinley, 1991). For reasons of simplicity, the fundamentals of DMIRT theory will be presented below limited to the two-dimensional case and the M2PL. The equations below also assume that the axes \(l\) are orthogonal. This introduces the constraint that \(\sum_{l=1}^{m}cos^2\alpha_{jl} = 1\), i.e., that squared cosines equal \(1\) so that \(cos^2\, \alpha_{im} = 1-\sum_{k=1}^{m-1} cos^2\, \alpha_{ik}\), for item \(i\), person \(j\), and \(k\) orthogonal axes.
The \(MDISC\) for item \(i\) represents the highest level of discrimination the item \(i\) can achieve located in a multidimensional latent trait space (also called the point of inflection), with \(m\) number of dimensions and \(a_{ik}\) item slope parameters (Reckase, 2009, Reckase & McKinley, 1991).
\(MDISC = A_i = \sqrt {\sum_{k = 1}^{m} a^{2}_{ik} }\)
Similarly to unidimensional modeling, the \(MDISC\) parameter, also denoted as \(A_i\), is the parameter that set the steepness of the slope of the item response function at the point of inflection. The slope is, similarly to the unidimensional case, assessed multiplied with the constant \(\frac{1}{4}\) (omitted in the equation above).
The item orientation towards the steepest slope is set by taking the arc cosine of the ratio between the \(a_{il}\), i.e., the slope value of item \(i\) on the coordinate axis \(l\), and the \(MDISC\) (Reckase, 2009, 1985).
\[ a_{il}= cos^{-1}\left(\frac{a_{il}}{\sqrt{\sum_{k=1}^m a^2_{ik}}}\right) \]
The resulting direction vector is a characteristic of the item that describes the angular orientation of an item in a multidimensional latent trait space.
The multidimensional version of the difficulty parameter, here denoted \(B\) as the DMIRT counterpart to the \(b\)-parameter in the unidimensional item response theory model, for item \(i\), is defined as the negative intercept \(d_i\) divided by the \(MDISC\) (Reckase, 2009, 1985).
\[ MDIFF=B_i=\frac{-d_i}{\sqrt{\sum_{k=1}^m a^2_{ik}}} \]
The \(MDIFF\) is interpreted similarly as the difficulty parameter in the unidimensional model. That is, higher values indicate that higher levels of ability for a probability of a correct response of more than .5 are necessary. Moreover, the \(MDIFF\), just as in the unidimensional model, sets the distance from the origin of the model to the point of inflection. However, in DMIRT analysis, the \(MDIFF\) becomes a multidimensional location parameter that indicates the distance from the origin to the point of the steepest slope following the direction vector given by the direction vector equation.
For Likert items that hold multiple item response functions, the \(MDIFF\) will be turned into an index that indicates the distance from the origin to the point of inflection for all response functions derived from an item. This, in turn, implies that the \(MDIFF\) will show the difficulty range for an item in the model.
The \(MDISC\) is visualized in DMIRT analysis by scaling the length of the vector arrows. In brief, the bottom location coordinates of the vector arrows, given by the \(MDIFF\) and direction vector, are multiplied with the \(MDISC\) so that items with higher \(MDISC\) have longer vector arrows (Reckase, 2009). Accordingly, shorter vector arrows indicate lower discrimination (which in turn indicates an increased amount of model violations of the item model).
Lastly, because the \(MDISC\) represents an item’s maximum level of discrimination in the model it is a global parameter that cannot be used to compare item discrimination locally. For the latter to be possible, the discrimination must be computed in a specified direction for the items. This can be achieved with the \(DDISC\), defined as follows (Reckase & McKinley, 1991).
\(DDISC = \sum_{k = 1}^{m} a_{ik} cos \alpha_{ik}\)
The \(DDISC\) describes the level of discrimination for one or more items in the model at the angle set by the direction of choice. Note, it is always true that \(DDISC \leq MDISC\).
In the D3mirt
package the \(DDISC\) is computed following the angle
orientation given by the construct vectors. Constructs, in this
context, refer to the assumption that a subset of items can measure a
higher-order latent variable. This is implemented as optional vectors
whose orientation is calculated as the average direction, i.e., the
average multidimensional discrimination of a subset of items (from one
item up to all items in the set) in the model. A construct vector will,
therefore, point in the direction of the maximum slope of what we might
call an imaginary item response function indicated by the items chosen
by the user.
Item subsets for the construct analysis are chosen by the user and can be exploratory (e.g., based on observations) or theoretical (e.g., fixed based on personality theory). If constructs are used, the output will include reporting of the \(DDISC\) parameter that shows how well all the items discriminate under the assumption that they measure in the direction indicated by the constructs in the analysis. That is, while the \(MDISC\) represents the maximum level of discrimination for the items in the model, the \(DDISC\) represents local discrimination that makes it possible to compare item discrimination set to follow a specific direction indicated by the constructs. Constructs are visually represented with vector arrows scaled to an arbitrary length.
The DMIRT method is currently limited to using the two-parameter
compensatory models. Regarding D3mirt
, the number of
dimensions is limited to three. However, in praxis, the number of
dimensions need not necessarily be exactly three, but up to three. This
since only two items in the set are needed to identify the model (see
the section on model identification below for more on the statistical
requirements).
The package includes the following main functions.
modid()
: D3mirt Model IdentificationD3mirt()
: 3D DMIRT Model Estimationplot()
: Graphical Output for D3mirt()
In what follows, the D3mirt
procedure and some of its
functions and options will be described using the built-in data set
“anes0809offwaves”. The data set (\(N = 1046,
M_{age} = 51.33, SD = 14.56, 57\%\) Female) is a subset from the
American National Election Survey (ANES) from the 2008-2009 Panel Study
Off Wave Questionnaires, December 2009 (DeBell, et al, 2010; https://electionstudies.org/data-center/2008-2009-panel-study/).
All items measure moral preferences and are positively scored of Likert
type, ranging from 1 = Strongly Disagree to 6 = Strongly
Agree. Demographic variables include age and gender
(male/female).
The sections below are sorted under the following headings.
modid()
Function
D3mirt
Model EstimationD3mirt()
Function
D3mirt()
Function Callplot()
Function
items
diff.level
scale
modid()
FunctionFor the D3mirt
analysis, two items with the following
properties must be chosen to identify the compensatory model (Reckase,
2009). The first item should not load on the second and third axes
(\(y\) and \(z\)), while the second item should not load
on the third axis (\(z\)). If this can
be empirically achieved, it will be possible to create the orthogonal
structure necessary for the analysis. The modid()
function
can help with this step in the process by suggesting what items to use.
The function does this based on an algorithmic approach that use factor
and item loading strength to order the model.
If the model is not known, the factor structure must be explored with
exploratory factor analysis (EFA). However, because D3mirt
analysis is based on the M2PL and the MGRM, it is recommended to use
multidimensional item response theory EFA methods, such as the EFA
option in mirt()
(Chalmers, 2012), from the package with
the same name, with ìtemtype = 'graded'
or
'2PL'
, so that the EFA is performed with the proper item
model. The mirt()
function is integrated into the
modid()
function so that the user needs only to provide a
data frame containing empirical data in the first argument of the
function. However, it is also possible to use the modid()
function without performing the EFA internally by setting
efa = FALSE
, if, for instance, a factor loading data frame
is already available.
Note, the EFA is only used to find model identification items that
meet the necessary DMIRT model specification requirements. The EFA model
itself is discarded after this step in the procedure and the user can,
therefore, try different types of rotation methods and compare model
identification results. Because the EFA in the mirt()
function takes a long time to perform, the item loadings from the EFA
for this example were stored in the package file “efa.Rdata” and are
loaded in the next code chunk below.
To start, load the data set from the ANES 2008-2009 Panel Study and remove columns for age and gender.
# Load data
data("anes0809offwaves")
x <- anes0809offwaves
x <- x[,3:22] # Remove columns for age and gender
If the default mode efa = TRUE
is not changed, the
function first does a EFA with three factors as default before
performing the model identification. In this example, however, the
factor loadings are already available in the package file “efa.Rdata”
and so the function call will only identify the model and not perform an
EFA (therefore efa = FALSE
).
# Optional: Load the EFA data for this example directly from the package file
load(system.file("extdata/efa.Rdata", package = "D3mirt"))
# Call to modid()
a <- modid(x, efa = FALSE)
summary(a)
#>
#> modid: 20 items and 3 factors
#>
#> Model identification items:
#> Item 1 W7Q3
#> Item 2 W7Q20
#>
#> Item.1 ABS
#> W7Q3 0.8547 0.0174
#> W7Q5 0.8199 0.0648
#> W7Q1 0.7589 0.0772
#> W7Q10 0.7239 0.0854
#>
#> Item.2 ABS
#> W7Q20 0.7723 0.0465
#> W7Q19 0.6436 0.0526
#> W7Q18 0.6777 0.0782
#>
#> SS Loadings
#> F2 5.3505
#> F1 2.1127
#> F3 1.6744
#>
#> F2 F1 F3
#> W7Q1 0.7589 0.0407 -0.0365
#> W7Q2 0.8901 -0.0263 -0.0838
#> W7Q3 0.8547 -0.0096 -0.0078
#> W7Q4 0.6628 0.0272 0.1053
#> W7Q5 0.8199 -0.0390 -0.0258
#> W7Q6 0.6654 0.0525 0.1054
#> W7Q7 0.5603 -0.0148 0.2087
#> W7Q8 0.5731 0.0390 0.1966
#> W7Q9 0.6151 0.0697 0.0918
#> W7Q10 0.7239 0.0371 -0.0483
#> W7Q11 0.2085 0.0959 0.5488
#> W7Q12 0.0755 -0.0853 0.5559
#> W7Q13 -0.0176 -0.0153 0.7654
#> W7Q14 -0.0407 0.1439 0.5629
#> W7Q15 0.1087 0.4556 -0.1111
#> W7Q16 0.1759 0.2100 0.1152
#> W7Q17 0.2160 0.5816 0.0261
#> W7Q18 -0.0560 0.6777 -0.0782
#> W7Q19 0.0589 0.6436 0.0526
#> W7Q20 -0.0735 0.7723 0.0465
The output consists of an \(S3\)
object of class modid
containing data frames with model
identification items, order of factor strength (based on sum of
squares), and item factor loadings. Using the summary()
function, we first get a printed message telling us the number of items
and the number of factors used in the analysis together with the
suggested model identification items. The items that are suggested by
modid()
to identify the model in this example are the items
“W7Q3”, for the \(x\)-axis, and
“W7Q20”, for the \(y\)-axis. Next, we
find data frames that hold all the model identification items
(Item.1...Item.n
) selected by modid()
together
with the items’ absolute sum score (ABS
), one frame for the
sum of squares for factors sorted in descending order, and one frame for
item factor loadings.
The absolute sum scores for the model identification items indicate statistical fit to the structural assumptions of the DMIRT model and are sorted with the lowest absolute sum score highest up. Accordingly, the top items are the items that best meet the necessary statistical requirements for model identification. Note, the order of the factors follows the model identification items so that item 1 comes from the strongest factor, item 2 from the second strongest, and so on.
If improper items are chosen the model will be hard to interpret, or
even unempirical if the data is forced to fit the model. The
modid()
function was, therefore, developed to hinder these
problems and to maximize the interpretive meaning by using an
algorithmic approach that can be user adjusted. In brief, in the default
automatic mode, modid()
starts by first calculating the sum
of squares loadings for the number of factors \(F\) in the data and then rearranging the
columns in \(x\) in decreasing order,
following the level of strength of the sum of squares loadings. Next,
the function creates a list containing the factor loadings on the first
factor, \(f_1\), and absolute sum
scores of the factor loadings on the remaining factors, i.e., \(F-f_1\), row-wise. The list is rearranged
in decreasing order row-wise from factor loading strength on \(f_1\).
Next, items are selected by scaling \(f_1\) loadings and then extracting the
items with the highest loadings on \(f_1\), up to a standard deviation of \(0.5\) (the default setting) as the lower
bound criteria counting from the top. That is, rows with raw factor
scores and absolute sum scores are extracted until the lower bound for
factor loadings on \(f_1\) is reached.
This allows the function to extract more rows in the case empirical
factor loadings are very similar in strength, while also excluding weak
loading items. As a last step, the function filters the list based on
the absolute sum score by using the upper
bound as the
selection criteria, i.e., items with an absolute sum score higher than
the upper
bound are removed. The results are recorded in
nested list before the function starts over with the next factor, \(f_2\), and so on.
Note, the absolute sum score is always assessed based on the number of factors less than the total number of factors, following the order of iteration, That is, iteration \(1\) use factor loadings from all factors \(F-f_1\), iteration \(2\) \(F-(f_{1,2})\), iteration \(3\) \(F-(f_{1,2,3})\), and so on, when calculating the absolute sum scores.
The model identification procedure orders the entire model so that the strongest loading item, from the strongest factor, always aligns perfectly with the \(x\)-axis and that the other items follow thereon. The model identification process is described in more detail below.
Sometimes, however, the model is hard to identify. If this happens, try the following in the order suggested. For more on the function arguments see the section below regarding the model identification procedure.
lower
bound in modid()
.fac.order
.upper
bound in modid()
.The latter (point 4) should, however, only be used as a last resort. This is because the upper bound sets the upper limit for item inclusion. Adjusting this limit too high means that the necessary statistical requirements are compromised. The lower limit (point 2), however, only increases the size of the item pool used for the item selection. It is, therefore, recommended to adjust the lower limit up and down to see if the output differs, and from that make the final decision.
# Call to modid with increased lower and higher bound
b <- modid(x, efa = FALSE, lower = 1, upper = 1 )
summary(b)
#>
#> modid: 20 items and 3 factors
#>
#> Model identification items:
#> Item 1 W7Q3
#> Item 2 W7Q17
#>
#> Item.1 ABS
#> W7Q3 0.8547 0.0174
#> W7Q5 0.8199 0.0648
#> W7Q1 0.7589 0.0772
#> W7Q10 0.7239 0.0854
#> W7Q2 0.8901 0.1101
#> W7Q4 0.6628 0.1325
#> W7Q6 0.6654 0.1579
#> W7Q9 0.6151 0.1615
#> W7Q7 0.5603 0.2234
#> W7Q8 0.5731 0.2356
#>
#> Item.2 ABS
#> W7Q17 0.5816 0.0261
#> W7Q20 0.7723 0.0465
#> W7Q19 0.6436 0.0526
#> W7Q18 0.6777 0.0782
#>
#> SS Loadings
#> F2 5.3505
#> F1 2.1127
#> F3 1.6744
#>
#> F2 F1 F3
#> W7Q1 0.7589 0.0407 -0.0365
#> W7Q2 0.8901 -0.0263 -0.0838
#> W7Q3 0.8547 -0.0096 -0.0078
#> W7Q4 0.6628 0.0272 0.1053
#> W7Q5 0.8199 -0.0390 -0.0258
#> W7Q6 0.6654 0.0525 0.1054
#> W7Q7 0.5603 -0.0148 0.2087
#> W7Q8 0.5731 0.0390 0.1966
#> W7Q9 0.6151 0.0697 0.0918
#> W7Q10 0.7239 0.0371 -0.0483
#> W7Q11 0.2085 0.0959 0.5488
#> W7Q12 0.0755 -0.0853 0.5559
#> W7Q13 -0.0176 -0.0153 0.7654
#> W7Q14 -0.0407 0.1439 0.5629
#> W7Q15 0.1087 0.4556 -0.1111
#> W7Q16 0.1759 0.2100 0.1152
#> W7Q17 0.2160 0.5816 0.0261
#> W7Q18 -0.0560 0.6777 -0.0782
#> W7Q19 0.0589 0.6436 0.0526
#> W7Q20 -0.0735 0.7723 0.0465
In this case, we find that the second item “W7Q17” is new. Observing
the statistical estimates we can also see that this outcome is related
to the increased lower
bound allowing weaker loading items
to be included in the selection process. Both the previous item
(“W7Q20”) and the new item (“W7Q17”) have an acceptable absolute sum
score, however. We can also note that the increased upper
bound allows more items to be included in the selection process. This is
most notable in the first data frame for Item.1
. In this
case, however, this had no effect on the final selection.
Another option (point 3) is to override the factor order with the
fac.order
argument. More specifically, modid()
orders factor by squared factor loadings so that the strongest factor is
used first, the second strongest factor is used second, and so on.
Sometimes, however, there is only a very small difference between the
squared factor loadings that in turn can cause problems, often only
observable at later stages. In such situations, it can be useful to
rearrange the factor order manually to see if the model solution
improves.
Since the squared factor loadings for factors 2 and 3 in this example are somewhat similar, it could be useful to compare the final results after manually overriding the factor order. The latter is, however, outside of the scope of this vignette.
# Override factor order by reversing columns in the original data frame
c <- modid(x, efa = FALSE, fac.order = c(3, 2, 1))
summary(c)
#>
#> modid: 20 items and 3 factors
#>
#> Model identification items:
#> Item 1 W7Q13
#> Item 2 W7Q3
#>
#> Item.1 ABS
#> W7Q13 0.7654 0.0329
#>
#> Item.2 ABS
#> W7Q3 0.8547 0.0096
#> W7Q2 0.8901 0.0263
#> W7Q10 0.7239 0.0371
#> W7Q5 0.8199 0.0390
#> W7Q1 0.7589 0.0407
#>
#> SS Loadings
#> F3 1.6744
#> F2 5.3505
#> F1 2.1127
#>
#> F3 F2 F1
#> W7Q1 -0.0365 0.7589 0.0407
#> W7Q2 -0.0838 0.8901 -0.0263
#> W7Q3 -0.0078 0.8547 -0.0096
#> W7Q4 0.1053 0.6628 0.0272
#> W7Q5 -0.0258 0.8199 -0.0390
#> W7Q6 0.1054 0.6654 0.0525
#> W7Q7 0.2087 0.5603 -0.0148
#> W7Q8 0.1966 0.5731 0.0390
#> W7Q9 0.0918 0.6151 0.0697
#> W7Q10 -0.0483 0.7239 0.0371
#> W7Q11 0.5488 0.2085 0.0959
#> W7Q12 0.5559 0.0755 -0.0853
#> W7Q13 0.7654 -0.0176 -0.0153
#> W7Q14 0.5629 -0.0407 0.1439
#> W7Q15 -0.1111 0.1087 0.4556
#> W7Q16 0.1152 0.1759 0.2100
#> W7Q17 0.0261 0.2160 0.5816
#> W7Q18 -0.0782 -0.0560 0.6777
#> W7Q19 0.0526 0.0589 0.6436
#> W7Q20 0.0465 -0.0735 0.7723
In this case, we find the item “W7Q3” which was previously suggested for the \(x\)-axis, is now suggested for the \(y\)-axis. For the \(x\)-axis, we find a new item, “W7Q13”.
Model identification items should preferably (a) have an absolute sum score of \(\leq .10\) and (b) have the highest factor loading scores on the factor of interest. Of these two criteria, (a) should be given the strongest weight in the selection decision. If these conditions cannot be met, the user is advised to proceed with caution since the loading scores, therefore, imply that an adequate orthogonal structure may not be empirically attainable. If problems in the model identification process occur, please follow the advice given above.
The modid()
function is not limited to three-dimensional
analysis and can be used on any number of dimensions. Although based on
suggestions on model identification given by Reckase (2009) for this
type of analysis, the function offers some expansions that introduce
more precision. The latter foremost consists in incorporating the sum of
squares and factor loadings in the item selection process (unless the
user has not specified otherwise). Experience tells us that this is good
practice that often leads to better results compared to other known
options. However, it is important to recognize that the model
identification procedure only gives suggestions to the model
specification, and there could be situations where the researcher should
consider other methods. Note, that two items can be found to identify
the model do not imply successful outcomes when using this methodology
(i.e., that the model is good). But it does suggest that the
methodology can be used and the results will be possible to
interpret in a meaningful way.
D3mirt()
FunctionThe D3mirt()
function takes in model parameters from a
three-dimensional compensatory model (either in the form of a data frame
or an S4 object of class ‘SingleGroupClass’ exported from the
mirt()
(Chalmers, 2012) function) and returns an \(S3\) object of class D3mirt
with lists of \(a\) and \(d\), \(MDISC\), and \(MDIFF\) parameters, direction cosines, and
spherical coordinates. Regarding the latter, spherical coordinates are
represented by \(\theta\) and \(\phi\). The \(\theta\) coordinate is the positive or
negative angle in degrees, starting from the \(x\)-axis, of the vector projections from
the vector arrows in the \(xz\)-plane
up to \(\pm 180°\). Note, the \(\theta\) angle is oriented following the
positive pole of the \(x\) and \(z\) axis so that the angle increases
clockwise in the graphical output. The \(\phi\) coordinate is the positive angle in
degrees from the \(y\)-axis and the
vectors. Note, the \(\rho\) coordinate
from the spherical coordinate system is in DMIRT represented by the
\(MDIFF\), and so is reported
separately.
If constructs are used, the function also returns construct direction cosines, spherical coordinates for the construct vector arrows, and \(DDISC\) parameters (one index per construct).
The three-dimensional compensatory model is specified so that all
items load on all three factors in the model, and all factors are
constrained to be orthogonal (see below). The fitting of the model is
preferably done with the mirt()
(Chalmers, 2012) function.
Observe that the START and FIXED commands are used to fix the slope
parameters on the second, \(a2\), and
third, \(a3\). factor for item \(_1\) (W7Q3), and the slope on the third,
\(a3\), factor for item \(i_2\) (W7Q20). However, because the fitting
of the compensatory model in the mirt()
function takes a
long time, the item parameters for this example are contained in a data
frame that is available in the package file “mod1.Rdata”.
# Load data
data("anes0809offwaves")
x <- anes0809offwaves
x <- x[,3:22] # Remove columns for age and gender
# Fit a three-dimensional graded response model with orthogonal factors
# Example below uses Likert items from the built-in data set "anes0809offwaves"
# Item W7Q3 and item W7Q20 was selected with `modid()`
# The model specification set all items in the data set (1-20)
# to load on all three factors (F1-F3)
# The START and FIXED commands are used on the two items to identify the DMIRT model
spec <- ' F1 = 1-20
F2 = 1-20
F3 = 1-20
START=(W7Q3,a2,0)
START=(W7Q3,a3,0)
START=(W7Q20,a3,0)
FIXED=(W7Q3,a2)
FIXED=(W7Q3,a3)
FIXED=(W7Q20,a3) '
mod1 <- mirt::mirt(x,
spec,
itemtype = 'graded',
SE = TRUE,
method = 'QMCEM')
D3mirt()
Function CallThe D3mirt()
function prints a short report containing
the number of items used and the levels of difficulty of the items when
the estimation is done. If construct vectors are used, the function will
also print the number of construct vectors and the names of the items
included in each construct (for an example see below). The
summary()
function is used to inspect the DMIRT
estimates.
# Optional: Load the mod1 as a data frame directly from the package file
load(system.file("extdata/mod1.Rdata", package = "D3mirt"))
# Call D3mirt()
g <- D3mirt(mod1)
summary(g) # Show summary of results
#>
#> D3mirt: 20 items and 5 levels of difficulty
#>
#> a1 a2 a3 d1 d2 d3 d4 d5
#> W7Q1 2.0298 0.1643 -0.1233 8.0868 7.0642 5.9877 3.2015 -0.4836
#> W7Q2 2.6215 -0.0027 -0.2585 9.2889 6.6187 4.5102 1.6648 -2.4440
#> W7Q3 2.7917 0.0000 0.0000 10.4835 7.5865 5.6764 2.7167 -1.1788
#> W7Q4 1.9046 0.1874 0.1491 7.3754 6.0467 4.9814 2.4830 -1.1146
#> W7Q5 2.2423 -0.0287 -0.0841 8.4266 6.6706 4.9047 1.8252 -1.8316
#> W7Q6 2.0022 0.2390 0.1567 8.0687 6.3578 4.9520 2.3300 -1.0189
#> W7Q7 1.6286 0.1033 0.3593 6.0178 4.8974 3.6908 1.6326 -1.3484
#> W7Q8 1.7775 0.2252 0.3528 6.9171 5.1822 3.7661 1.4844 -1.8332
#> W7Q9 1.7199 0.2493 0.1278 7.5587 4.9755 3.3648 0.9343 -2.2094
#> W7Q10 1.7696 0.1272 -0.1407 8.3639 5.7396 4.2862 1.9646 -0.6642
#> W7Q11 1.4237 0.4673 1.0433 6.2180 4.6920 3.5430 1.1918 -1.8573
#> W7Q12 0.7605 0.0409 0.9366 4.1360 2.8770 2.3419 1.1790 -0.4239
#> W7Q13 1.1285 0.2910 1.6943 5.8922 4.4009 3.4430 1.8955 -0.6009
#> W7Q14 0.7448 0.4828 0.9785 5.3891 3.9333 3.0258 0.8144 -1.5868
#> W7Q15 0.4551 0.7870 -0.1606 4.3206 3.0544 2.3969 0.9187 -0.9705
#> W7Q16 0.6237 0.4139 0.1799 3.7249 2.0305 1.1658 -0.0612 -1.8085
#> W7Q17 1.1893 1.3412 0.0564 6.9011 5.8022 4.9344 2.7915 -0.0041
#> W7Q18 0.4107 1.3542 -0.1368 3.7837 2.0985 1.4183 0.1828 -1.9855
#> W7Q19 0.8580 1.4098 0.2279 4.4978 2.6483 1.6731 0.3740 -1.9966
#> W7Q20 0.7357 1.9068 0.0000 4.6378 2.3633 1.2791 -0.3431 -2.9190
#>
#> MDISC MDIFF1 MDIFF2 MDIFF3 MDIFF4 MDIFF5
#> W7Q1 2.0402 -3.9638 -3.4625 -2.9348 -1.5692 0.2370
#> W7Q2 2.6343 -3.5262 -2.5125 -1.7121 -0.6320 0.9278
#> W7Q3 2.7917 -3.7553 -2.7176 -2.0333 -0.9731 0.4222
#> W7Q4 1.9196 -3.8421 -3.1500 -2.5950 -1.2935 0.5806
#> W7Q5 2.2441 -3.7550 -2.9725 -2.1856 -0.8133 0.8162
#> W7Q6 2.0225 -3.9894 -3.1435 -2.4485 -1.1520 0.5038
#> W7Q7 1.6710 -3.6013 -2.9308 -2.2087 -0.9770 0.8070
#> W7Q8 1.8261 -3.7880 -2.8379 -2.0624 -0.8129 1.0039
#> W7Q9 1.7425 -4.3377 -2.8553 -1.9310 -0.5362 1.2679
#> W7Q10 1.7797 -4.6995 -3.2249 -2.4083 -1.1039 0.3732
#> W7Q11 1.8259 -3.4055 -2.5697 -1.9404 -0.6527 1.0172
#> W7Q12 1.2071 -3.4263 -2.3834 -1.9400 -0.9767 0.3512
#> W7Q13 2.0564 -2.8653 -2.1401 -1.6743 -0.9218 0.2922
#> W7Q14 1.3211 -4.0794 -2.9773 -2.2904 -0.6164 1.2011
#> W7Q15 0.9232 -4.6800 -3.3085 -2.5963 -0.9951 1.0513
#> W7Q16 0.7699 -4.8381 -2.6373 -1.5142 0.0795 2.3490
#> W7Q17 1.7934 -3.8481 -3.2353 -2.7514 -1.5566 0.0023
#> W7Q18 1.4217 -2.6613 -1.4760 -0.9976 -0.1286 1.3966
#> W7Q19 1.6661 -2.6996 -1.5895 -1.0042 -0.2245 1.1984
#> W7Q20 2.0438 -2.2693 -1.1563 -0.6259 0.1679 1.4282
#>
#> D.Cos X D.Cos Y D.Cos Z Theta Phi
#> W7Q1 0.9949 0.0805 -0.0604 -3.4748 85.3808
#> W7Q2 0.9952 -0.0010 -0.0981 -5.6305 90.0597
#> W7Q3 1.0000 0.0000 0.0000 0.0000 90.0000
#> W7Q4 0.9922 0.0976 0.0777 4.4767 84.3967
#> W7Q5 0.9992 -0.0128 -0.0375 -2.1474 90.7326
#> W7Q6 0.9900 0.1182 0.0775 4.4765 83.2140
#> W7Q7 0.9746 0.0618 0.2150 12.4409 86.4543
#> W7Q8 0.9734 0.1233 0.1932 11.2272 82.9174
#> W7Q9 0.9870 0.1431 0.0734 4.2512 81.7735
#> W7Q10 0.9943 0.0715 -0.0791 -4.5468 85.9010
#> W7Q11 0.7797 0.2560 0.5714 36.2355 75.1698
#> W7Q12 0.6300 0.0339 0.7759 50.9236 88.0565
#> W7Q13 0.5488 0.1415 0.8239 56.3330 81.8637
#> W7Q14 0.5638 0.3655 0.7407 52.7234 68.5629
#> W7Q15 0.4929 0.8525 -0.1739 -19.4324 31.5149
#> W7Q16 0.8102 0.5376 0.2336 16.0853 57.4764
#> W7Q17 0.6631 0.7478 0.0315 2.7156 41.5968
#> W7Q18 0.2888 0.9525 -0.0962 -18.4194 17.7246
#> W7Q19 0.5150 0.8462 0.1368 14.8767 32.1990
#> W7Q20 0.3600 0.9330 0.0000 0.0000 21.0997
After the printed message, the factor loadings and the difficulty parameters from the compensatory model are reported followed by all necessary DMIRT estimates. Examples of how DMIRT estimates can be used when reporting results are given below in the item and dimensionality analysis.
Constructs can be included in the analysis by creating one or more
nested lists that indicate what items belong to what construct. Such a
nested list can be created using all items in the set down to a single
item. From this, the D3mirt()
function finds the average
direction of the subset of items contained in each nested list, by
adding and normalizing the direction cosines for the items and scaling
the construct direction vector to an arbitrary length. The length of the
construct vector arrows can be adjusted by the user.
The construct vector arrows can contribute to the analysis by (a) visualizing the average direction for a subset set of items, and (b) showing how all items discriminate locally in the direction of the construct vector with the help of the \(DDISC\) index.
The constructs included below were grouped based on exploratory reasons, i.e., because these items cluster in the model (observable in the graphical output).
# Call to D3mirt(), including optional nested lists for three constructs
# Item W7Q16 is not included in any construct because of model violations
# The model violations for the W7Q16 item can be seen when plotting the model
c <- list(list(1,2,3,4,5,6,7,8,9,10),
list(11,12,13,14),
list(15,17,18,19,20))
g <- D3mirt(mod1, c)
summary(g)
#>
#> D3mirt: 20 items and 5 levels of difficulty
#>
#> Constructs:
#> Vector 1: W7Q1, W7Q2, W7Q3, W7Q4, W7Q5, W7Q6, W7Q7, W7Q8, W7Q9, W7Q10
#> Vector 2: W7Q11, W7Q12, W7Q13, W7Q14
#> Vector 3: W7Q15, W7Q17, W7Q18, W7Q19, W7Q20
#>
#> a1 a2 a3 d1 d2 d3 d4 d5
#> W7Q1 2.0298 0.1643 -0.1233 8.0868 7.0642 5.9877 3.2015 -0.4836
#> W7Q2 2.6215 -0.0027 -0.2585 9.2889 6.6187 4.5102 1.6648 -2.4440
#> W7Q3 2.7917 0.0000 0.0000 10.4835 7.5865 5.6764 2.7167 -1.1788
#> W7Q4 1.9046 0.1874 0.1491 7.3754 6.0467 4.9814 2.4830 -1.1146
#> W7Q5 2.2423 -0.0287 -0.0841 8.4266 6.6706 4.9047 1.8252 -1.8316
#> W7Q6 2.0022 0.2390 0.1567 8.0687 6.3578 4.9520 2.3300 -1.0189
#> W7Q7 1.6286 0.1033 0.3593 6.0178 4.8974 3.6908 1.6326 -1.3484
#> W7Q8 1.7775 0.2252 0.3528 6.9171 5.1822 3.7661 1.4844 -1.8332
#> W7Q9 1.7199 0.2493 0.1278 7.5587 4.9755 3.3648 0.9343 -2.2094
#> W7Q10 1.7696 0.1272 -0.1407 8.3639 5.7396 4.2862 1.9646 -0.6642
#> W7Q11 1.4237 0.4673 1.0433 6.2180 4.6920 3.5430 1.1918 -1.8573
#> W7Q12 0.7605 0.0409 0.9366 4.1360 2.8770 2.3419 1.1790 -0.4239
#> W7Q13 1.1285 0.2910 1.6943 5.8922 4.4009 3.4430 1.8955 -0.6009
#> W7Q14 0.7448 0.4828 0.9785 5.3891 3.9333 3.0258 0.8144 -1.5868
#> W7Q15 0.4551 0.7870 -0.1606 4.3206 3.0544 2.3969 0.9187 -0.9705
#> W7Q16 0.6237 0.4139 0.1799 3.7249 2.0305 1.1658 -0.0612 -1.8085
#> W7Q17 1.1893 1.3412 0.0564 6.9011 5.8022 4.9344 2.7915 -0.0041
#> W7Q18 0.4107 1.3542 -0.1368 3.7837 2.0985 1.4183 0.1828 -1.9855
#> W7Q19 0.8580 1.4098 0.2279 4.4978 2.6483 1.6731 0.3740 -1.9966
#> W7Q20 0.7357 1.9068 0.0000 4.6378 2.3633 1.2791 -0.3431 -2.9190
#>
#> MDISC MDIFF1 MDIFF2 MDIFF3 MDIFF4 MDIFF5
#> W7Q1 2.0402 -3.9638 -3.4625 -2.9348 -1.5692 0.2370
#> W7Q2 2.6343 -3.5262 -2.5125 -1.7121 -0.6320 0.9278
#> W7Q3 2.7917 -3.7553 -2.7176 -2.0333 -0.9731 0.4222
#> W7Q4 1.9196 -3.8421 -3.1500 -2.5950 -1.2935 0.5806
#> W7Q5 2.2441 -3.7550 -2.9725 -2.1856 -0.8133 0.8162
#> W7Q6 2.0225 -3.9894 -3.1435 -2.4485 -1.1520 0.5038
#> W7Q7 1.6710 -3.6013 -2.9308 -2.2087 -0.9770 0.8070
#> W7Q8 1.8261 -3.7880 -2.8379 -2.0624 -0.8129 1.0039
#> W7Q9 1.7425 -4.3377 -2.8553 -1.9310 -0.5362 1.2679
#> W7Q10 1.7797 -4.6995 -3.2249 -2.4083 -1.1039 0.3732
#> W7Q11 1.8259 -3.4055 -2.5697 -1.9404 -0.6527 1.0172
#> W7Q12 1.2071 -3.4263 -2.3834 -1.9400 -0.9767 0.3512
#> W7Q13 2.0564 -2.8653 -2.1401 -1.6743 -0.9218 0.2922
#> W7Q14 1.3211 -4.0794 -2.9773 -2.2904 -0.6164 1.2011
#> W7Q15 0.9232 -4.6800 -3.3085 -2.5963 -0.9951 1.0513
#> W7Q16 0.7699 -4.8381 -2.6373 -1.5142 0.0795 2.3490
#> W7Q17 1.7934 -3.8481 -3.2353 -2.7514 -1.5566 0.0023
#> W7Q18 1.4217 -2.6613 -1.4760 -0.9976 -0.1286 1.3966
#> W7Q19 1.6661 -2.6996 -1.5895 -1.0042 -0.2245 1.1984
#> W7Q20 2.0438 -2.2693 -1.1563 -0.6259 0.1679 1.4282
#>
#> D.Cos X D.Cos Y D.Cos Z Theta Phi
#> W7Q1 0.9949 0.0805 -0.0604 -3.4748 85.3808
#> W7Q2 0.9952 -0.0010 -0.0981 -5.6305 90.0597
#> W7Q3 1.0000 0.0000 0.0000 0.0000 90.0000
#> W7Q4 0.9922 0.0976 0.0777 4.4767 84.3967
#> W7Q5 0.9992 -0.0128 -0.0375 -2.1474 90.7326
#> W7Q6 0.9900 0.1182 0.0775 4.4765 83.2140
#> W7Q7 0.9746 0.0618 0.2150 12.4409 86.4543
#> W7Q8 0.9734 0.1233 0.1932 11.2272 82.9174
#> W7Q9 0.9870 0.1431 0.0734 4.2512 81.7735
#> W7Q10 0.9943 0.0715 -0.0791 -4.5468 85.9010
#> W7Q11 0.7797 0.2560 0.5714 36.2355 75.1698
#> W7Q12 0.6300 0.0339 0.7759 50.9236 88.0565
#> W7Q13 0.5488 0.1415 0.8239 56.3330 81.8637
#> W7Q14 0.5638 0.3655 0.7407 52.7234 68.5629
#> W7Q15 0.4929 0.8525 -0.1739 -19.4324 31.5149
#> W7Q16 0.8102 0.5376 0.2336 16.0853 57.4764
#> W7Q17 0.6631 0.7478 0.0315 2.7156 41.5968
#> W7Q18 0.2888 0.9525 -0.0962 -18.4194 17.7246
#> W7Q19 0.5150 0.8462 0.1368 14.8767 32.1990
#> W7Q20 0.3600 0.9330 0.0000 0.0000 21.0997
#>
#> C.Cos X C.Cos Y C.Cos Z Theta Phi
#> C1 0.9970 0.0687 0.0364 2.0923 86.0608
#> C2 0.6412 0.2026 0.7402 49.1006 78.3129
#> C3 0.4720 0.8814 -0.0207 -2.5136 28.1932
#>
#> DDISC1 DDISC2 DDISC3
#> W7Q1 2.0305 1.2435 1.1054
#> W7Q2 2.6040 1.4890 1.2403
#> W7Q3 2.7832 1.7899 1.3177
#> W7Q4 1.9171 1.3695 1.0611
#> W7Q5 2.2305 1.3696 1.0348
#> W7Q6 2.0183 1.4482 1.1524
#> W7Q7 1.6439 1.3311 0.8523
#> W7Q8 1.8004 1.4464 1.0301
#> W7Q9 1.7364 1.2478 1.0289
#> W7Q10 1.7679 1.0562 0.9503
#> W7Q11 1.4895 1.7797 1.0622
#> W7Q12 0.7951 1.1891 0.3756
#> W7Q13 1.2068 2.0366 0.7541
#> W7Q14 0.8113 1.2996 0.7568
#> W7Q15 0.5019 0.3324 0.9118
#> W7Q16 0.6568 0.6169 0.6555
#> W7Q17 1.2799 1.0759 1.7422
#> W7Q18 0.4975 0.4364 1.3902
#> W7Q19 0.9606 1.0044 1.6428
#> W7Q20 0.8645 0.8580 2.0278
In contrast to the previous example, the printed message now includes
the construct vectors and their respective items. Moreover, compared to
the previous function call to D3mirt()
, there are also two
extra data frames: one frame with direction cosines (\(D.Cos X, D.Cos Y, D.Cos Z\)) and spherical
coordinates (\(\theta, \phi\)) for the
constructs, and one frame with the \(DDISC\) estimates, containing the \(DDISC_{1,2,3}\) parameters for the items
corresponding to the three constructs \((1,2,3)\) (assigned with c in the
example above).
plot()
FunctionThe plot()
method for objects of class
D3mirt
is built on functions from the rgl
package (Adler & Murdoch, 2023) for visualization with OpenGL. The
output consists of a three-dimensional interactive RGL device,
displaying vector arrows with the latent dimensions running along the
orthogonal axes centered at zero. If polytomous items are used each item
will have multiple arrows, representing the multiple item step response
functions, running along the same direction in the model.
When plotting the D3mirt
model with plot()
,
it is possible to visually observe statistical violations in the
graphical output returned. For instance, shorter vector arrows indicate
weaker discrimination and therefore also higher amounts of model
violations. As another example, if an item struggles or even fail to
describe any of the latent variables in the model, it can often lead to
an extreme stretch of the \(MDIFF\)
range. This is comparable to trace lines turning horizontal in a
unidimensional item response theory model. Some examples of model
violations and within-dimensionality will be given in the illustration
below.
Graphing in default mode by calling plot()
will return
an RGL device that will appear in an external window as a
three-dimensional interactive object that can be rotated manually by the
user. In this illustration, however, all RGL devices are plotted as
inline interactive objects with the help of R markdown. Note, the
view
argument is used in all function calls to
plot()
below. This was only done for optimizing the size of
the RGL device (the default is view = c(15, 20, 7)
) when
creating this R Markdown vignette.
An example of how the output can be described could be the following.
As can be seen in the figure, the pattern in the data indicates the presence of foremost two main latent constructs indicated by the items, one aligned with the \(x\)-axis and one approaching the \(y\)-axis. We might also suspect the presence of a third construct located close to the \(xy\)-plane, between the \(x\) and \(z\) axes. Studying the content of the items, the labels Compassion, Fairness, and Conformity were introduced.
To get a better understanding of the interrelation of the data, constructs can be added to asses the average angle when grouping items. As mentioned above, in this example the items have been grouped in constructs in an exploratory fashion, i.e., based on their observed location in the model. Note, item W7Q16 was not included in any of the constructs because of a high amount of model violation tendencies and notable within-multidimensionality.
To plot constructs alongside item vectors, change to
constructs = TRUE
. The constructs can be named with strings
as input to the construct.lab
argument. In this example,
construct labels were chosen based on item content.
# Plot RGL device with constructs visible and named
plot(g, constructs = TRUE,
construct.lab = c("Compassion", "Fairness", "Conformity"),
view = c(15, 20, 0.6))
An example of how the output can be described could be as follows.
The angles of the constructs inform us that Compassion (\(\theta = 2.092^{\circ}\), \(\phi = 86.061^{\circ}\)) and Conformity (\(\theta = -2.514^{\circ}\),\(\phi = 28.193^{\circ}\)) have some within-multidimensional tendencies but they are both more or less orthogonal to the \(z\)-axis. Next, we find Fairness (\(\theta = 49.101^{\circ}\), \(\phi = 78.313^{\circ}\)) with clear within-multidimensional tendencies with respect to the \(x\)-axis. Thus, the output indicates that Compassion and Conformity could be independent constructs but that Fairness seems not to be.
items
A subset of items can be plotted for a more thorough investigation
using the items
argument. In the example below, all
constructs are plotted together with the items used for the conformity
construct. In the function call, the numerical indicators in the
items
argument follow the item order in the original data
frame (see ?anes0809offwaves
).
# A selection of Conformity items from the model plotted with constructs
plot(g, constructs = TRUE,
items = c(15,17,18,19,20),
construct.lab = c("Compassion", "Fairness", "Conformity"),
view = c(15, 20, 0.6))
The plot()
function also allows plotting a single item
by entering a single number indicating what item that should be
displayed. As was mentioned above, the W7Q16 was not included in any of
the constructs because the item showed signs of measurement problems.
For example, the short vector arrows indicate high amounts of model
violations and the location of the item in the model also indicates that
the item is within-multidimensional and that it does not seem to belong
to any construct explicitly. Typing in \(16\) in the items
argument
allows for a closer look.
# Item W7Q16 has location 16 in the data set (gender and age excluded)
# The item is plotted together with constructs to aid the visual interpretation
plot(g, constructs = TRUE,
items = 16,
construct.lab = c("Compassion", "Fairness", "Conformity"),
view = c(15, 20, 0.6))
An example of how the output can be described could be as follows.
The figure shows that item W7Q16 is located at \(\theta = 16.085^{\circ}\), \(\phi = 57.476^{\circ}\), indicating that the item is within-multidimensional with respect to the \(x\) and \(y\)-axis; but much less so with respect to the \(z\)-axis. In addition, the directional discrimination further underscores that the item does not seem to measure any particular construct (\(DDISC_1 = .657\), \(DDISC_2 = .617\), \(DDISC_3 = .656\)). The global discrimination (\(MDISC = .770\), \(MDIFF_{range} = [-4.838, 2.349]\)) is also the lowest of all discrimination scores in the model. This, combined, implies that the item in question does not seem to fit the three-dimensional DMIRT used in this analysis and should therefore be removed or adapted. On a side note, we can also note that item W7Q15, \(MDISC = .923\), \(MDIFF_{range} = [-4.680, 1.051]\)) has the second lowest global discrimination score. However, this item does seem to belong to the Conformity construct, observable when comparing angle orientation (\(\theta = -19.432^{\circ}, \phi = 31.515^{\circ}\)) and directional discrimination (\(DDISC_1 = .502\), \(DDISC_2 = .332\), \(DDISC_3 = .912\)).
diff.level
The user has the option of plotting on one level of difficulty at a
time with the diff.level
argument studying the entire
scale, a subset of items, or on one item at a time. Note,
difficulty refers to the number of item response functions in
the items, i.e., the total number of response options minus one. In this
case, \(6\) response options were used
which means that the model has \(5\)
levels of difficulty.
scale
The D3mirt()
function returns item vector coordinates
estimated with and without the \(MDISC\) as a scalar for the arrow length.
When the \(MDISC\) is not used for the
arrow length, all item vector arrows are scaled to one unit length. This
allows the user to graph the item vector arrows with plot()
set to a uniform length. This can help reduce visual clutter in the
graphical output. To view the item vector arrows without the \(MDISC\), set scale = TRUE
.
The plot()
function can also display respondents in the
three-dimensional model represented as spheres whose coordinates are
derived from the respondent’s factor scores. This allows for a profile
analysis in which respondents can be separated, or subset, conditioned
on single or multiple criteria and then plotted. The resulting output
shows where the respondents are located in the model, and, accordingly,
what model profile best describes them. Similarly, respondent categories
can be simultaneously compared to see if a group-level effect can be
visually observed.
To do this, the user must first extract respondent factor scores with
fscores()
(Chalmers, 2012) and then separate or select a
subset of respondent rows based on one or more criteria. The resulting
data frame is imputed in the profiles
argument. Generally,
it can be useful to hide vector arrows with hide = TRUE
when plotting respondent profiles to avoid visual cluttering. The
example below separates respondents using the gender variable included
in the built-in data set. To save some time in running the examples, the
fscores()
output is stored in the package file
“fscores.Rdata” and is loaded in the next code chunk below.
# Extract respondent factor scores from mod1 with fscores() function
f <- mirt::fscores(mod1,
method="EAP",
full.scores = TRUE,
full.scores.SE = FALSE, QMC = TRUE)
# Optional: Load the respondent factor scores for this example directly from the package file
load(system.file("extdata/fscores.Rdata", package = "D3mirt"))
# Attach f to the gender variable (column 2 from anes0809offwaves data set; "W3XGENDER")
# Use cbind with fscores() output attached first
data("anes0809offwaves")
x <- anes0809offwaves
z <- data.frame(cbind(f, x[,2]))
The plot()
function uses as.factor()
to
count the number of factor levels in the data imputed in the
levels
argument. This means that raw data can be used as is
but the number of colors in the color vectors argument
(sphere.col
) may need to be adapted. In the example below,
the criteria variable for gender only hold two factor levels and
therefore only two colors in the color vector are needed.
Call plot()
with the respondent data frame \(z\) in the profiles
argument
and the levels
argument with the levels column subset from
\(z\). In the function call below, the
axes in the model are named using the x.lab
,
y.lab
, and z.lab
arguments following the
direction of the constructs. Note, the model axes represent
unidimensional singular structures, or traits, in this case borrowing
the names of the constructs.
# Plot profiles with item vector arrows hidden
# Score levels: 1 = Blue ("male") and 2 = Red ("female")
plot(g, hide = TRUE,
profiles = z,
levels = z[,4],
sphere.col = c("blue", "red"),
x.lab = "Compassion",
y.lab="Conformity",
z.lab="Fairness",
view = c(16, 20, 0.6))
An example of how the output can be described could be as follows.
In the figure, it can be observed a simple profile on gender in which more women tend to have higher levels of Compassion. When rotating the model \(90^{\circ}\) clockwise, there seems not to be any easily observable gender difference related to Conformity or Fairness.
The use of rep()
function makes it possible to create
groups based on factor levels. This can be useful when a criterion
variable has a wide data range, such as an age variable. More
specifically, a color vector for the sphere.col
argument
can be created with color names repeated by rep()
. When
plotting, the plot()
function will pick colors from the
sphere.col
argument following the factor order in the
levels
argument. The example below illustrates this when
comparing respondents 30 years or younger against 70 years or older.
First, we must count the number of factor levels in the variable.
This can be done with, the nlevels(as.factor(x))
. Then we
use the output from the latter to set the appropriate size of color
vector for sphere.col
.
# Column bind fscores() with age variable ("W3Xage")
y <- data.frame(cbind(f, x[,1]))
# Subset data frame y conditioned on age <= 30
z1 <- subset(y, y[,4] <= 30)
# Subset data frame y conditioned on age >= 70
z2 <- subset(y, y[,4] >= 70)
# Row bind z1 and z2
z <- rbind(z1,z2)
# Check number of factor levels with nlevels() and as.factor()
nlevels(as.factor(z1[,4]))
#> [1] 14
nlevels(as.factor(z2[,4]))
#> [1] 16
# Use rep() to create a color vector to color groups based on the nlevels() output
# z1 has 14 factor levels and z2 has 16 factor levels
# z1 respondents are colored red and z2 are colored blue
colvec <- c(rep("red", 14),
rep("blue", 16))
# Call plot() with profile data on age with item vector arrows hidden
plot(g, hide = TRUE,
profiles = z,
levels = z[,4],
sphere.col = colvec,
x.lab = "Compassion",
y.lab="Conformity",
z.lab="Fairness",
view = c(15, 20, 0.6))
An example of how the output can be described could be as follows.
As can be seen, the figure indicates an age effect in which older individuals have higher levels of Conformity. Rotating the model to the left also shows that older individuals may have slightly higher levels of Fairness, even if the effect is less clear. There does not seem to be any difference in Compassion, however. To sum, we can say, therefore, that the analysis indicates a possibility that older individuals may have a moral profile consisting of high Conformity and possibly also high Fairness.
It is also possible to plot a confidence interval in the shape of an ellipse surrounding the spheres. In the example below, the younger individuals (\(\leq30\)) are selected and plotted with a \(95\%\) CI.
# Column bind fscores() with age variable ("W3Xage")
y <- data.frame(cbind(f, x[,1]))
# Subset data frame y conditioned on age <= 30
z1 <- subset(y, y[,4] <= 30)
# Use rep() to create a color vector to color groups based on the nlevels() output
# z1 has 14 factor levels
colvec <- c(rep("red", 14))
To plot the CI, the ci
argument is set to
TRUE
. The color of the sphere was also changed from the
default grey80
to orange
in the example below.
Note, the CI limit can be adjusted with the
ci.level
argument.
# Call plot() with profile data on age with item vector arrows hidden
plot(g, hide = TRUE,
profiles = z1,
levels = z1[,4],
sphere.col = colvec,
x.lab = "Compassion",
y.lab="Conformity",
z.lab="Fairness",
ci = TRUE,
ci.level = 0.95,
ellipse.col = "orange",
view = c(15, 20, 0.6))
An example of how the output can be described could be as follows.
In the figures we can see a tendency for a profile on age in which younger individuals could be described as less oriented towards Conformity. We can also observe a tendency for what could be an interaction effect in which higher levels of Conformity seem to be associated with lower levels of Fairness.
Some options for exporting the RGL device are shown below. Over and
above these, it is also possible to export graphical devices in R
Markdown documents with rgl::hookwebgl()
together with
graphical options for knitr, as was done when creating this
vignette.
# Export an open RGL device to the console that can be saved as an html or image file
plot(g, constructs = TRUE)
s <- scene3d()
rgl::rglwidget(s,
width = 1040,
height = 1040)
# Export a snap shoot of an open RGL device directly to file
plot(g, constructs = TRUE)
rgl::rgl.snapshot('RGLdevice.png',
fmt = 'png')
Adler, D., & Murdoch, D. (2023). Rgl: 3d Visualization Using OpenGL [Computer software]. https://dmurdoch.github.io/rgl/index.html
Chalmers, R., P. (2012). mirt: A Multidimensional Item Response Theory Package for the R Environment. Journal of Statistical Software, 48(6), 1-29. https://doi.org/10.18637/jss.v048.i06
DeBell, M., Krosnick, J. A., & Lupia, A.(2010). Methodology Report and User’s Guide for the 2008-2009 ANES Panel Study. Palo Alto, CA, and Ann Arbor, MI: Stanford University and the University of Michigan.
Muraki, E., & Carlson, J. E. (1995). Full-Information Factor Analysis for Polytomous Item Responses. Applied Psychological Measurement, 19(1), 73-90. https://doi.org/10.1177/014662169501900109
Reckase, M. D.(2009).Multidimensional Item Response Theory.Springer. https://doi.org/10.1007/978-0-387-89976-3
Reckase, M. D.(1985). The Difficulty of Test Items That Measure More Than One Ability. Applied Psychological Measurement, 9(4),401-412. https://doi.org/10.1177/014662168500900409
Reckase, M. D., & McKinley, R. L. (1991). The Discriminating Power of Items That Measure More Than One Dimension. Applied Psychological Measurement, 15(4), 361-373. https://doi.org/10.1177/014662169101500407