Skip to contents

Computes the M2 (Maydeu-Olivares & Joe, 2006) statistic when all data are dichotomous, the collapsed M2* statistic (collapsing over univariate and bivariate response categories; see Cai and Hansen, 2013), and the hybrid C2 statistic which only collapses only the bivariate moments (Cai and Monro, 2014). The C2 variant is mainly useful when polytomous response models do not have sufficient degrees of freedom to compute M2*. This function also computes associated fit indices that are based on fitting the null model. Supports single and multiple-group models. If the latent trait density was approximated (e.g., Davidian curves, Empirical histograms, etc) then passing use_dentype_estimate = TRUE will use the internally saved quadrature and density components (where applicable).

Usage

M2(
  obj,
  type = "M2*",
  calcNull = TRUE,
  quadpts = NULL,
  theta_lim = c(-6, 6),
  CI = 0.9,
  residmat = FALSE,
  QMC = FALSE,
  suppress = 1,
  ...
)

Arguments

obj

an estimated model object from the mirt package

type

type of fit statistic to compute. Options are "M2", "M2*" for the univariate and bivariate collapsed version of the M2 statistic ("M2" currently limited to dichotomous response data only), and "C2" for a hybrid between M2 and M2* where only the bivariate moments are collapsed

calcNull

logical; calculate statistics for the null model as well? Allows for statistics such as the limited information TLI and CFI. Only valid when items all have a suitable null model (e.g., those created via createItem will not)

quadpts

number of quadrature points to use during estimation. If NULL, a suitable value will be chosen based on the rubric found in fscores

theta_lim

lower and upper range to evaluate latent trait integral for each dimension

CI

numeric value from 0 to 1 indicating the range of the confidence interval for RMSEA. Default returns the 90% interval

residmat

logical; return the residual matrix used to compute the SRMSR statistic? Only the lower triangle of the residual correlation matrix will be returned (the upper triangle is filled with NA's)

QMC

logical; use quasi-Monte Carlo integration? Useful for higher dimensional models. If quadpts not specified, 5000 nodes are used by default

suppress

a numeric value indicating which parameter residual dependency combinations to flag as being too high. Absolute values for the standardized residuals greater than this value will be returned, while all values less than this value will be set to NA. Must be used in conjunction with the argument residmat = TRUE

...

additional arguments to pass

Value

Returns a data.frame object with the M2-type statistic, along with the degrees of freedom, p-value, RMSEA (with 90% confidence interval), SRMSR for each group, and optionally the TLI and CFI model fit statistics if calcNull = TRUE.

References

Cai, L. & Hansen, M. (2013). Limited-information goodness-of-fit testing of hierarchical item factor models. British Journal of Mathematical and Statistical Psychology, 66, 245-276.

Cai, L. & Monro, S. (2014). A new statistic for evaluating item response theory models for ordinal data. National Center for Research on Evaluation, Standards, & Student Testing. Technical Report.

Chalmers, R., P. (2012). mirt: A Multidimensional Item Response Theory Package for the R Environment. Journal of Statistical Software, 48(6), 1-29. doi:10.18637/jss.v048.i06

Maydeu-Olivares, A. & Joe, H. (2006). Limited information goodness-of-fit testing in multidimensional contingency tables. Psychometrika, 71, 713-732.

Author

Phil Chalmers rphilip.chalmers@gmail.com

Examples

# \donttest{
dat <- as.matrix(expand.table(LSAT7))
(mod1 <- mirt(dat, 1))
#> 
Iteration: 1, Log-Lik: -2668.786, Max-Change: 0.18243
Iteration: 2, Log-Lik: -2663.691, Max-Change: 0.13637
Iteration: 3, Log-Lik: -2661.454, Max-Change: 0.10231
Iteration: 4, Log-Lik: -2659.430, Max-Change: 0.04181
Iteration: 5, Log-Lik: -2659.241, Max-Change: 0.03417
Iteration: 6, Log-Lik: -2659.113, Max-Change: 0.02911
Iteration: 7, Log-Lik: -2658.812, Max-Change: 0.00456
Iteration: 8, Log-Lik: -2658.809, Max-Change: 0.00363
Iteration: 9, Log-Lik: -2658.808, Max-Change: 0.00273
Iteration: 10, Log-Lik: -2658.806, Max-Change: 0.00144
Iteration: 11, Log-Lik: -2658.806, Max-Change: 0.00118
Iteration: 12, Log-Lik: -2658.806, Max-Change: 0.00101
Iteration: 13, Log-Lik: -2658.805, Max-Change: 0.00042
Iteration: 14, Log-Lik: -2658.805, Max-Change: 0.00025
Iteration: 15, Log-Lik: -2658.805, Max-Change: 0.00026
Iteration: 16, Log-Lik: -2658.805, Max-Change: 0.00023
Iteration: 17, Log-Lik: -2658.805, Max-Change: 0.00023
Iteration: 18, Log-Lik: -2658.805, Max-Change: 0.00021
Iteration: 19, Log-Lik: -2658.805, Max-Change: 0.00019
Iteration: 20, Log-Lik: -2658.805, Max-Change: 0.00017
Iteration: 21, Log-Lik: -2658.805, Max-Change: 0.00017
Iteration: 22, Log-Lik: -2658.805, Max-Change: 0.00015
Iteration: 23, Log-Lik: -2658.805, Max-Change: 0.00015
Iteration: 24, Log-Lik: -2658.805, Max-Change: 0.00013
Iteration: 25, Log-Lik: -2658.805, Max-Change: 0.00013
Iteration: 26, Log-Lik: -2658.805, Max-Change: 0.00011
Iteration: 27, Log-Lik: -2658.805, Max-Change: 0.00011
Iteration: 28, Log-Lik: -2658.805, Max-Change: 0.00010
#> 
#> Call:
#> mirt(data = dat, model = 1)
#> 
#> Full-information item factor analysis with 1 factor(s).
#> Converged within 1e-04 tolerance after 28 EM iterations.
#> mirt version: 1.44.3 
#> M-step optimizer: BFGS 
#> EM acceleration: Ramsay 
#> Number of rectangular quadrature: 61
#> Latent density type: Gaussian 
#> 
#> Log-likelihood = -2658.805
#> Estimated parameters: 10 
#> AIC = 5337.61
#> BIC = 5386.688; SABIC = 5354.927
#> G2 (21) = 31.7, p = 0.0628
#> RMSEA = 0.023, CFI = NaN, TLI = NaN
M2(mod1)
#>             M2 df          p     RMSEA     RMSEA_5   RMSEA_95      SRMSR
#> stats 11.93769  5 0.03565165 0.0372683 0.008950922 0.06496573 0.03195919
#>             TLI       CFI
#> stats 0.9369332 0.9684666
resids <- M2(mod1, residmat=TRUE) #lower triangle of residual correlation matrix
resids
#>             Item.1      Item.2       Item.3       Item.4 Item.5
#> Item.1          NA          NA           NA           NA     NA
#> Item.2 -0.02212010          NA           NA           NA     NA
#> Item.3 -0.03265942  0.03335601           NA           NA     NA
#> Item.4  0.05155184 -0.01642572 -0.012476892           NA     NA
#> Item.5  0.05443241 -0.03867705 -0.001860395 7.235425e-05     NA
summary(resids[lower.tri(resids)])
#>      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
#> -0.038677 -0.020697 -0.007169  0.001519  0.025035  0.054432 

# M2 with missing data present
dat[sample(1:prod(dim(dat)), 250)] <- NA
mod2 <- mirt(dat, 1)
#> 
Iteration: 1, Log-Lik: -2547.291, Max-Change: 0.18194
Iteration: 2, Log-Lik: -2539.425, Max-Change: 0.13938
Iteration: 3, Log-Lik: -2536.809, Max-Change: 0.10708
Iteration: 4, Log-Lik: -2534.711, Max-Change: 0.05139
Iteration: 5, Log-Lik: -2534.472, Max-Change: 0.04305
Iteration: 6, Log-Lik: -2534.308, Max-Change: 0.03620
Iteration: 7, Log-Lik: -2533.924, Max-Change: 0.01092
Iteration: 8, Log-Lik: -2533.912, Max-Change: 0.00981
Iteration: 9, Log-Lik: -2533.904, Max-Change: 0.00868
Iteration: 10, Log-Lik: -2533.883, Max-Change: 0.00250
Iteration: 11, Log-Lik: -2533.882, Max-Change: 0.00195
Iteration: 12, Log-Lik: -2533.882, Max-Change: 0.00175
Iteration: 13, Log-Lik: -2533.881, Max-Change: 0.00121
Iteration: 14, Log-Lik: -2533.881, Max-Change: 0.00111
Iteration: 15, Log-Lik: -2533.881, Max-Change: 0.00050
Iteration: 16, Log-Lik: -2533.881, Max-Change: 0.00043
Iteration: 17, Log-Lik: -2533.881, Max-Change: 0.00184
Iteration: 18, Log-Lik: -2533.881, Max-Change: 0.00036
Iteration: 19, Log-Lik: -2533.881, Max-Change: 0.00026
Iteration: 20, Log-Lik: -2533.881, Max-Change: 0.00025
Iteration: 21, Log-Lik: -2533.881, Max-Change: 0.00026
Iteration: 22, Log-Lik: -2533.881, Max-Change: 0.00023
Iteration: 23, Log-Lik: -2533.881, Max-Change: 0.00023
Iteration: 24, Log-Lik: -2533.881, Max-Change: 0.00108
Iteration: 25, Log-Lik: -2533.881, Max-Change: 0.00033
Iteration: 26, Log-Lik: -2533.881, Max-Change: 0.00020
Iteration: 27, Log-Lik: -2533.881, Max-Change: 0.00015
Iteration: 28, Log-Lik: -2533.881, Max-Change: 0.00071
Iteration: 29, Log-Lik: -2533.881, Max-Change: 0.00055
Iteration: 30, Log-Lik: -2533.881, Max-Change: 0.00043
Iteration: 31, Log-Lik: -2533.881, Max-Change: 0.00033
Iteration: 32, Log-Lik: -2533.881, Max-Change: 0.00020
Iteration: 33, Log-Lik: -2533.881, Max-Change: 0.00012
Iteration: 34, Log-Lik: -2533.881, Max-Change: 0.00005
M2(mod2)
#>             M2 df         p      RMSEA RMSEA_5   RMSEA_95      SRMSR       TLI
#> stats 8.181306  5 0.1465225 0.02523684       0 0.05513589 0.03213259 0.9636641
#>             CFI
#> stats 0.9818321

# C2 statistic (useful when polytomous IRT models have too few df)
pmod <- mirt(Science, 1)
#> 
Iteration: 1, Log-Lik: -1629.361, Max-Change: 0.50660
Iteration: 2, Log-Lik: -1617.374, Max-Change: 0.25442
Iteration: 3, Log-Lik: -1612.894, Max-Change: 0.16991
Iteration: 4, Log-Lik: -1610.306, Max-Change: 0.10461
Iteration: 5, Log-Lik: -1609.814, Max-Change: 0.09162
Iteration: 6, Log-Lik: -1609.534, Max-Change: 0.07363
Iteration: 7, Log-Lik: -1609.030, Max-Change: 0.03677
Iteration: 8, Log-Lik: -1608.988, Max-Change: 0.03200
Iteration: 9, Log-Lik: -1608.958, Max-Change: 0.02754
Iteration: 10, Log-Lik: -1608.878, Max-Change: 0.01443
Iteration: 11, Log-Lik: -1608.875, Max-Change: 0.00847
Iteration: 12, Log-Lik: -1608.873, Max-Change: 0.00515
Iteration: 13, Log-Lik: -1608.872, Max-Change: 0.00550
Iteration: 14, Log-Lik: -1608.872, Max-Change: 0.00318
Iteration: 15, Log-Lik: -1608.871, Max-Change: 0.00462
Iteration: 16, Log-Lik: -1608.871, Max-Change: 0.00277
Iteration: 17, Log-Lik: -1608.870, Max-Change: 0.00145
Iteration: 18, Log-Lik: -1608.870, Max-Change: 0.00175
Iteration: 19, Log-Lik: -1608.870, Max-Change: 0.00126
Iteration: 20, Log-Lik: -1608.870, Max-Change: 0.00025
Iteration: 21, Log-Lik: -1608.870, Max-Change: 0.00285
Iteration: 22, Log-Lik: -1608.870, Max-Change: 0.00108
Iteration: 23, Log-Lik: -1608.870, Max-Change: 0.00022
Iteration: 24, Log-Lik: -1608.870, Max-Change: 0.00059
Iteration: 25, Log-Lik: -1608.870, Max-Change: 0.00014
Iteration: 26, Log-Lik: -1608.870, Max-Change: 0.00068
Iteration: 27, Log-Lik: -1608.870, Max-Change: 0.00065
Iteration: 28, Log-Lik: -1608.870, Max-Change: 0.00019
Iteration: 29, Log-Lik: -1608.870, Max-Change: 0.00061
Iteration: 30, Log-Lik: -1608.870, Max-Change: 0.00012
Iteration: 31, Log-Lik: -1608.870, Max-Change: 0.00012
Iteration: 32, Log-Lik: -1608.870, Max-Change: 0.00058
Iteration: 33, Log-Lik: -1608.870, Max-Change: 0.00055
Iteration: 34, Log-Lik: -1608.870, Max-Change: 0.00015
Iteration: 35, Log-Lik: -1608.870, Max-Change: 0.00052
Iteration: 36, Log-Lik: -1608.870, Max-Change: 0.00010
# This fails with too few df:
# M2(pmod)
# This, however, works:
M2(pmod, type = 'C2')
#>             M2 df           p     RMSEA    RMSEA_5  RMSEA_95      SRMSR
#> stats 19.17929  2 6.84337e-05 0.1482174 0.09234204 0.2116368 0.07257313
#>             TLI       CFI
#> stats 0.7300952 0.9100317

# }