Learn R Programming

mirt (version 1.3)

multipleGroup: Multiple Group Estimation

Description

multipleGroup performs a full-information maximum-likelihood multiple group analysis for dichotomous and polytomous data under the item response theory paradigm using either Cai's (2010) Metropolis-Hastings Robbins-Monro (MHRM) algorithm or with an EM algorithm approach. This function may be used for detecting differential item functioning (DIF), thought the DIF function may provide a more convenient approach.

Usage

multipleGroup(data, model, group, itemtype = NULL, guess = 0, upper = 1,
  SE = FALSE, SE.type = "crossprod", invariance = "", pars = NULL,
  method = "EM", constrain = NULL, parprior = NULL, calcNull = TRUE,
  draws = 5000, quadpts = NULL, TOL = NULL, grsm.block = NULL,
  rsm.block = NULL, key = NULL, technical = list(), accelerate = TRUE,
  empiricalhist = FALSE, GenRandomPars = FALSE, verbose = TRUE, ...)

Arguments

data
a matrix or data.frame that consists of numerically ordered data, with missing data coded as NA
model
a single model object returned from mirt.model() declaring how the factor model is to be estimated. See mirt.model for more details
group
a character vector indicating group membership
invariance
a character vector containing the following possible options: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

Additionally, specifying specific item name bundles (from colnames(data)) wil

guess
initial (or fixed) values for the pseudo-guessing parameter. Can be entered as a single value to assign a global guessing parameter or may be entered as a numeric vector for each item
upper
initial (or fixed) upper bound parameters for 4-PL model. Can be entered as a single value to assign a global upper bound parameter or may be entered as a numeric vector corresponding to each item
accelerate
see mirt for more details
SE
logical; estimate the information matrix for standard errors?
SE.type
see mirt for more details
verbose
logical; display iteration history during estimation?
draws
the number of Monte Carlo draws to estimate the log-likelihood
quadpts
the number of quadratures to be used per dimensions when method = 'EM'
calcNull
logical; calculate the Null model for fit statics (e.g., TLI)?
method
a character indicating whether to use the EM ('EM') or the MH-RM ('MHRM') algorithm
type
type of plot to view; can be 'info' to show the test information function, 'infocontour' for the test information contours, 'SE' for the test standard error function, 'RE' for the relative effici
empiricalhist
logical; estimate prior distribution using an empirical histogram approach. see mirt for details
GenRandomPars
logical; generate random starting values prior to optimization instead of using the fixed internal starting values?
key
see mirt for details
itemtype
see mirt for details
constrain
see mirt for details
grsm.block
see mirt for details
rsm.block
see mirt for details
parprior
see mirt for details
pars
see mirt for details
TOL
see mirt for details
...
additional arguments to be passed
technical
list specifying subtle parameters that can be adjusted. See mirt for details

Details

By default the estimation in multipleGroup assumes that the models are maximally independent, and therefore could initially be performed by sub-setting the data and running identical models with mirt and aggregating the results (e.g., log-likelihood). However, constrains may be imposed across groups by invoking various invariance keywords and constrain = ... arguments, by inputting user specified design matrix from mod2values or from passing pars = 'values', or by supplying a constrain list for user defined equality constraints between parameters.

See Also

anova-method, coef-method, summary-method, residuals-method, plot-method, expand.table, key2binary, mirt.model, mirt, bfactor, multipleGroup, mixedmirt, wald, itemplot, fscores, M2, extract.item, iteminfo, testinfo, probtrace, boot.mirt, imputeMissing, itemfit, mod2values, simdata, createItem, mirtCluster, DIF

Examples

Run this code
#single factor
set.seed(12345)
a <- matrix(abs(rnorm(15,1,.3)), ncol=1)
d <- matrix(rnorm(15,0,.7),ncol=1)
itemtype <- rep('dich', nrow(a))
N <- 1000
dataset1 <- simdata(a, d, N, itemtype)
dataset2 <- simdata(a, d, N, itemtype, mu = .1, sigma = matrix(1.5))
dat <- rbind(dataset1, dataset2)
group <- c(rep('D1', N), rep('D2', N))
models <- mirt.model('F1 = 1-15')

mod_configural <- multipleGroup(dat, models, group = group) #completely separate analyses
#limited information fit statistics
M2(mod_configural)

mod_metric <- multipleGroup(dat, models, group = group, invariance=c('slopes')) #equal slopes
#equal intercepts, free variance and means
mod_scalar2 <- multipleGroup(dat, models, group = group,
                             invariance=c('slopes', 'intercepts', 'free_var','free_means'))
mod_scalar1 <- multipleGroup(dat, models, group = group,  #fixed means
                             invariance=c('slopes', 'intercepts', 'free_var'))
mod_fullconstrain <- multipleGroup(dat, models, group = group,
                             invariance=c('slopes', 'intercepts'))

summary(mod_scalar2)
coef(mod_scalar2)
residuals(mod_scalar2)
plot(mod_configural)
plot(mod_configural, type = 'score')
plot(mod_configural, type = 'trace')
plot(mod_configural, type = 'trace', which.items = 1:4)
itemplot(mod_configural, 2)
itemplot(mod_configural, 2, type = 'RE')

anova(mod_metric, mod_configural) #equal slopes only
anova(mod_scalar2, mod_metric) #equal intercepts, free variance and mean
anova(mod_scalar1, mod_scalar2) #fix mean
anova(mod_fullconstrain, mod_scalar1) #fix variance


#test whether first 6 slopes should be equal across groups
values <- multipleGroup(dat, models, group = group, pars = 'values')
values
constrain <- list(c(1, 63), c(5,67), c(9,71), c(13,75), c(17,79), c(21,83))
equalslopes <- multipleGroup(dat, models, group = group, constrain = constrain)
anova(equalslopes, mod_configural)

#same as above, but using mirt.model syntax
newmodel <- mirt.model('
    F = 1-15
    CONSTRAINB = (1-6, a1)')
equalslopes <- multipleGroup(dat, newmodel, group = group)
coef(equalslopes)

#############
#DIF test for each item (using all other items as anchors)
itemnames <- colnames(dat)
refmodel <- multipleGroup(dat, models, group = group, SE=TRUE,
                             invariance=c('free_means', 'free_varcov', itemnames))

#loop over items (in practice, run in parallel to increase speed). May be better to use ?DIF
estmodels <- vector('list', ncol(dat))
for(i in 1:ncol(dat))
    estmodels[[i]] <- multipleGroup(dat, models, group = group, verbose = FALSE, calcNull=FALSE,
                             invariance=c('free_means', 'free_varcov', itemnames[-i]))

(anovas <- lapply(estmodels, anova, object2=refmodel, verbose=FALSE))

#family-wise error control
p <- do.call(rbind, lapply(anovas, function(x) x[2, 'p']))
p.adjust(p, method = 'BH')

#same as above, except only test if slopes vary (1 df)
#constrain all intercepts
estmodels <- vector('list', ncol(dat))
for(i in 1:ncol(dat))
    estmodels[[i]] <- multipleGroup(dat, models, group = group, verbose = FALSE, calcNull=FALSE,
                             invariance=c('free_means', 'free_varcov', 'intercepts',
                             itemnames[-i]))

(anovas <- lapply(estmodels, anova, object2=refmodel, verbose=FALSE))

#quickly test with Wald test using DIF()
mod_configural2 <- multipleGroup(dat, models, group = group, SE=TRUE)
DIF(mod_configural2, which.par = c('a1', 'd'), Wald=TRUE, p.adjust = 'fdr')

#############
#multiple factors

a <- matrix(c(abs(rnorm(5,1,.3)), rep(0,15),abs(rnorm(5,1,.3)),
rep(0,15),abs(rnorm(5,1,.3))), 15, 3)
d <- matrix(rnorm(15,0,.7),ncol=1)
mu <- c(-.4, -.7, .1)
sigma <- matrix(c(1.21,.297,1.232,.297,.81,.252,1.232,.252,1.96),3,3)
itemtype <- rep('dich', nrow(a))
N <- 1000
dataset1 <- simdata(a, d, N, itemtype)
dataset2 <- simdata(a, d, N, itemtype, mu = mu, sigma = sigma)
dat <- rbind(dataset1, dataset2)
group <- c(rep('D1', N), rep('D2', N))

#group models
model <- mirt.model('
   F1 = 1-5
   F2 = 6-10
   F3 = 11-15')

#define mirt cluster to use parallel architecture
mirtCluster()

#EM approach (not as accurate with 3 factors, but generally good for quick model comparisons)
mod_configural <- multipleGroup(dat, model, group = group) #completely separate analyses
mod_metric <- multipleGroup(dat, model, group = group, invariance=c('slopes')) #equal slopes
mod_fullconstrain <- multipleGroup(dat, model, group = group, #equal means, slopes, intercepts
                             invariance=c('slopes', 'intercepts'))

anova(mod_metric, mod_configural)
anova(mod_fullconstrain, mod_metric)

#same as above, but with MHRM (generally  more accurate with 3+ factors, but slower)
mod_configural <- multipleGroup(dat, model, group = group, method = 'MHRM')
mod_metric <- multipleGroup(dat, model, group = group, invariance=c('slopes'), method = 'MHRM')
mod_fullconstrain <- multipleGroup(dat, model, group = group, method = 'MHRM',
                             invariance=c('slopes', 'intercepts'))

anova(mod_metric, mod_configural)
anova(mod_fullconstrain, mod_metric)

############
#polytomous item example
set.seed(12345)
a <- matrix(abs(rnorm(15,1,.3)), ncol=1)
d <- matrix(rnorm(15,0,.7),ncol=1)
d <- cbind(d, d-1, d-2)
itemtype <- rep('graded', nrow(a))
N <- 1000
dataset1 <- simdata(a, d, N, itemtype)
dataset2 <- simdata(a, d, N, itemtype, mu = .1, sigma = matrix(1.5))
dat <- rbind(dataset1, dataset2)
group <- c(rep('D1', N), rep('D2', N))
model <- mirt.model('F1 = 1-15')

mod_configural <- multipleGroup(dat, model, group = group)
plot(mod_configural)
plot(mod_configural, type = 'SE')
itemplot(mod_configural, 1)
itemplot(mod_configural, 1, type = 'info')
fs <- fscores(mod_configural)
head(fs[["D1"]])
fscores(mod_configural, method = 'EAPsum')

# constrain slopes within each group to be equal (but not across groups)
model2 <- mirt.model('F1 = 1-15
                      CONSTRAIN = (1-15, a1)')
mod_configural2 <- multipleGroup(dat, model2, group = group)
plot(mod_configural2, type = 'SE')
plot(mod_configural2, type = 'RE')
itemplot(mod_configural2, 10)

############
## empirical histogram example (normal and bimodal groups)
set.seed(1234)
a <- matrix(rlnorm(50, .2, .2))
d <- matrix(rnorm(50))
ThetaNormal <- matrix(rnorm(2000))
ThetaBimodal <- scale(matrix(c(rnorm(1000, -2), rnorm(1000,2)))) #bimodal
Theta <- rbind(ThetaNormal, ThetaBimodal)
dat <- simdata(a, d, 4000, itemtype = 'dich', Theta=Theta)
group <- rep(c('G1', 'G2'), each=2000)

EH <- multipleGroup(dat, 1, group=group, empiricalhist = TRUE, invariance = colnames(dat))
coef(EH)
plot(EH, type = 'empiricalhist', npts = 60)

#dif test for item 1
EH1 <- multipleGroup(dat, 1, group=group, empiricalhist = TRUE, invariance = colnames(dat)[-1])
anova(EH, EH1)

Run the code above in your browser using DataLab