library(irtoys) ### # Please cite the following paper when using the code # Wang,c., Chen, P., & Jiang, S. (2019) Item Calibration Methods with Multiple Subscale Multistage Testing. # Journal of Educational Measurement. ###############Single-group MML/EM ######################################## library(irtoys) ##group is a index vector with the same length as row in repsonse matrix, ##elements (1,...G) indicate group membership ipest.sg <- function(resp,Q=21,eps =1e-3,max.iter=50) { N <- nrow(resp) J <- ncol(resp) D <- 1.7 #One set of quadrature points and weights based on standard normal GH <- normal.qu(Q) X <- GH$quad.points A <- GH$quad.weights #starting values b <- rep(0,J) a <- rep(1,J) #intermediate quantities ngq <- double(Q) rgq <- double(Q) pstar <- matrix(,J,Q) pi <- double(N) niq <- liq <- matrix(double(N*Q),N,Q) pjq <-ljq <- matrix(double(J*Q),J) df.a <- df.b <- 1 iter <- 0 while(max(df.a)>eps & max(df.b)>eps & itereps & max(df.b)>eps & iter0)) ll } #gradient function for a and b gr <- function(ip){ a <- ip[1] b <- ip[2] p <- 1/(1+exp(-a*D*(X-b))) c( -sum((rgq-ngq*p)*(X-b)*D*(rgq>0)), sum((rgq-ngq*p)*a*D*(rgq>0)) ) } #optimization, retrieve a and b estimate temp <- optim(c(temp.a,temp.b),lik,gr,method = "L-BFGS-B", lower =c (0,-Inf))$par temp.a <- temp[1] temp.b <- temp[2] a[j] <- temp.a b[j] <- temp.b } #calculate the amout of change to compare with termination criterion df.a <- abs(aold-a) df.b <- abs(bold-b) } return(list(est=cbind(a,b),iter=iter)) } #end of function ###############Multiple group MML/EM with normal theta per group: M-MML-N ################## ipest.mg2 <- function(resp,group,mu=0,sig=1,Q=21,eps =1e-3,max.iter=50) { N <- nrow(resp) J <- ncol(resp) D <- 1.7 #starting values for the first and third group population parameters mu1 <- -1 mu3 <- 1 #var sig1 <- 1 sig3 <- 1 #three sets of X and A for the three groups, to be updated in each cycle of EM G <- length(unique(group)) A <- X <- matrix(,G,Q) #starting values b <- rep(0,J) a <- rep(1,J) #intermediate quantities ngq <- matrix(double(G*Q),G) rgq <- matrix(double(G*Q),G) pstar <- matrix(,J,Q) pi <- double(N) niq <- liq <- matrix(double(N*Q),N,Q) pjq <-ljq <- matrix(double(J*Q),J) df.a <- df.b <- 1 iter <- 0 #start of EM cycle while(max(df.a)>eps & max(df.b)>eps & iter0)) } gr <- function(ip){ a <- ip[1] b <- ip[2] p <- 1/(1+exp(-a*D*(X-b))) c( -sum((rgq-ngq*p)*(X-b)*D*(rgq>0)), sum((rgq-ngq*p)*a*D*(rgq>0)) ) } temp <- optim(c(temp.a,temp.b),lik,gr,method = "L-BFGS-B", lower =c (0,-Inf))$par temp.a <- temp[1] temp.b <- temp[2] a[j] <- temp.a b[j] <- temp.b } #after all item parameters are updated, calculate population parameters Ng <- table(group) Xiq <- X[rep(1:nrow(X),times=Ng),] muiq <- Xiq*niq Xi <- apply(muiq,1,sum) mu1 <- mean(Xi[group==1]) mu3 <- mean(Xi[group==3]) sigiq <- apply((Xiq-Xi)^2*niq,1,sum) sig1 <- mean(sigiq[group==1]+(Xi[group==1]-mu1)^2) sig3 <- mean(sigiq[group==3]+(Xi[group==3]-mu3)^2) df.a <- abs(aold-a) df.b <- abs(bold-b) } return(list(est=cbind(a,b),pop=c(mu1,mu3,sig1,sig3),iter=iter)) } #end of function