## File Name: isop.dich.R
## File Version: 3.17
######################################################################
# Fitting the ISOP and ADISOP model
isop.dich <- function( dat, score.breaks=NULL, merge.extreme=TRUE,
conv=.0001, maxit=1000, epsilon=.025,
progress=TRUE ){
#*****************************************
# convert matrix into matrix format
dat <- as.matrix(dat)
I <- ncol(dat)
# define response matrix
dat.resp <- 1-is.na( dat )
if( max( dat, na.rm=TRUE ) > 1 ){
stop("Use isop.poly for polytomous data!")
}
if ( ! is.null(score.breaks) ){
merge.extreme <- FALSE }
# different scores of students
stud.p <- rowMeans( dat, na.rm=TRUE )
if (merge.extreme){
score.breaks <- ( c(0,2:(I-1), I+1 ) -.5 ) / I
}
if ( ! is.null( score.breaks) ){
stud.p <- cut( stud.p, breaks=score.breaks, labels=FALSE)
}
# different items
item.p <- colMeans( dat, na.rm=TRUE )
item.ps <- sort( item.p, index.return=TRUE)
dat <- dat[, item.ps$ix ]
# score groups students
scores <- sort( unique( stud.p ) )
SC <- length(scores)
# scoring of students
res <- isop.scoring( dat )
person <- res$person
person$scoregroup <- stud.p
item <- res$item
p.itemcat <- res$p.itemcat
score.itemcat <- res$score.itemcat
# create item groups
# create table
freq.correct <- matrix( NA, SC, I )
rownames(freq.correct) <- paste0("score_", scores )
colnames(freq.correct) <- colnames(dat)
wgt <- freq.correct
# percent correct
a1 <- stats::aggregate( dat==1, list( stud.p ), mean, na.rm=TRUE )
freq.correct <- a1[,-1]
# weights
a1 <- stats::aggregate( dat.resp, list( stud.p ), sum, na.rm=TRUE )
wgt <- a1[,-1]
# ISOP Model
res.isop <- fit.isop( freq.correct, wgt, conv=conv,
maxit=maxit, progress=progress )
f1 <- freq.correct
f1 <- res.isop$fX
# ADISOP Model (start with the fitted isop solution)
res.adisop <- fit.adisop( freq.correct=f1, wgt, conv=conv, maxit=maxit,
epsilon=epsilon, progress=progress )
wgt1 <- ( wgt / colSums( wgt ) ) / ncol(wgt)
res.adisop$fit <- sqrt( sum( ( freq.correct - res.adisop$fX )^2 * wgt1 ) )
# logistic function
res.logistic <- fit.logistic( freq.correct, wgt,
scores=scores / max( scores), item.p=item.ps$x,
conv, maxit, progress=progress )
# fit generalized logistic function
# res.genlogistic <- fit.genlogistic( freq.correct, wgt, scores=scores / max( scores), item.p=item.ps$x,
# conv, maxit, progress=progress )
# fit alpha1 parameter
#*******
# collect likelihood values
ll <- data.frame( "model"=c("saturated", "isop", "adisop", "logistic"),
"ll"=c(res.isop$ll$ll.ind, res.isop$ll$ll.isop,
res.adisop$ll$ll.adisop, res.logistic$ll$ll.logistic ) )
ll$llcase <- c( res.isop$ll$llcase.ind, res.isop$ll$llcase.isop,
res.adisop$ll$llcase.adisop,
res.logistic$ll$llcase.logistic )
#*****
# model fit
fit <- c( res.isop$fit, res.adisop$fit, res.logistic$fit )
names(fit) <- c("isop","adisop","logistic")
# probability tables
prob.isop <- calc.prob.from.freq.dich( fittedfreq=res.isop$fX )
prob.adisop <- calc.prob.from.freq.dich( fittedfreq=res.adisop$fX )
prob.logistic <- calc.prob.from.freq.dich( fittedfreq=res.logistic$fX )
prob.saturated <- calc.prob.from.freq.dich( fittedfreq=freq.correct )
#*******
#* collect results
res <- list( "freq.correct"=freq.correct, "wgt"=wgt,
"prob.saturated"=prob.saturated,
"prob.isop"=prob.isop, "prob.adisop"=prob.adisop,
"prob.logistic"=prob.logistic,
"ll"=ll, "fit"=fit,
"person"=person, "item"=item,
"p.itemcat"=p.itemcat, "score.itemcat"=score.itemcat,
"fit.isop"=res.isop, "fit.adisop"=res.adisop,
"fit.logistic"=res.logistic, "s2"=Sys.time(), "dat"=dat,
"model"="isop.dich")
class(res) <- "isop"
return(res)
}
##########################################################
# calculate probability table from fitted frequencies
calc.prob.from.freq.dich <- function( fittedfreq ){
SC <- nrow(fittedfreq)
I <- ncol(fittedfreq)
prob1 <- array( NA, dim=c(I,2,SC ) )
prob1[,2,] <- t(fittedfreq)
prob1[,1,] <- 1-t(fittedfreq)
return(prob1)
}
#############################################################
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.