## ----setup, include=FALSE-----------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)

## ----eval=F-------------------------------------------------------------------
# ## Install packages from CRAN repository
# install.packages(c("dplyr", "grmtree", "mirt", "psych"))

## ----message=FALSE, warning=FALSE---------------------------------------------
library(dplyr)        # For data manipulation
library(grmtree)      # For tree-based GRM DIF Test
library(mirt)         # For traditional GRM
library(psych)        # For psychometrics

## ----message=FALSE------------------------------------------------------------
## Load the data
data("grmtree_data", package = "grmtree")

## Take a glimpse at the data
glimpse(grmtree_data)

## ----warning=FALSE------------------------------------------------------------
## Create the response data (the 8 MOS-SS items)
response_data <- grmtree_data %>% 
  dplyr::select(MOS_Listen:MOS_Understand) %>% 
  mutate_at(vars(starts_with("MOS")), as.ordered)

## Create response as outcomes
response_data$resp <- data.matrix(response_data[, 1:8])

## ----eval=FALSE---------------------------------------------------------------
# ## Calculate the polychoric correlation of items
# polycorr_mos <- polychoric(response_data$resp, global=FALSE)$rho
# 
# ## Return the eigen values
# polycorr_eigen_mos <- eigen(polycorr_mos)$values
# round(polycorr_eigen_mos, 3)
# 
# ## Ratio of first and second eigen value
# mos_ratio <- round(round(polycorr_eigen_mos, 3)[1]/round(polycorr_eigen_mos, 3)[2],3)
# 
# ## Print the result
# mos_ratio
# 
# cat("The ratio of the first-to-second eigen value is", mos_ratio,
#     "which is >4 suggesting that the unidimensionality assumption is satisfied", "\n")

## ----eval=FALSE---------------------------------------------------------------
# ## Scree plot of eigen values
# plot(1:length(polycorr_eigen_mos), polycorr_eigen_mos,
#      type = "b", pch = 20, xlab = "", ylab = "Eigen values")

## ----eval=FALSE---------------------------------------------------------------
# ## Perform EFA with 1 factors
# efa_mos <- fa(response_data$resp, nfactors = 1, rotate = "varimax", fm = "mle")
# 
# ## Print the results
# summary(efa_mos)
# print(efa_mos, sort=TRUE)
# efa_mos$loadings
# 
# ## Visualizing factor structure using fa.diagram
# fa.diagram(efa_mos, main = "EFA Factor Structure")
# 
# ## Scree plot to visualize the number of factors
# fa.parallel(response_data$resp, fa = "fa")

## -----------------------------------------------------------------------------
## Create GRM
mos_grm <- mirt(data = response_data$resp, 
                model = 1,
                itemtype = "graded", SE = TRUE, method = "EM",
                verbose = FALSE)

## -----------------------------------------------------------------------------
## Get the coefficients
mos_coef <- coef(mos_grm, IRTpars = T, simplify = TRUE)
mos_coef

## Get the residuals
residuals(mos_grm, type = "Q3")

## Compute the M2 model fit statistic
M2(mos_grm, type = "C2")

## Infit and outfit statistics
mirt::itemfit(mos_grm, c('S_X2', 'infit'), method = 'EAP')

## Could also use method = 'ML'

## ----eval = FALSE-------------------------------------------------------------
# ## Plot the category response curves
# plot(mos_grm, type = 'trace')
# 
# ## Plot the test information
# plot(mos_grm, type = 'info')

## ----grmtree-process, echo=FALSE, out.width="75%", fig.align='center', fig.cap="GRMTree implementation process showing the four-step recursive partitioning approach for detecting differential item functioning"----
knitr::include_graphics("GRMTree.png")

## ----warning=FALSE------------------------------------------------------------

## Prepare the data
resp.data <- grmtree_data %>% 
  mutate_at(vars(starts_with("MOS")), as.ordered) %>% 
  mutate_at(vars(c(sex, residency, depressed,
                   Education, job, smoker,
                   multimorbidity)), as.factor) 

## Explore the data
head(resp.data)

## Check the structure of the data
glimpse(resp.data)

## Create response as outcomes
resp.data$resp <- data.matrix(resp.data[, 1:8])

## GRMTree control parameters with Benjamini-Hochberg
grm_control <- grmtree.control(
  minbucket = 350,
  p_adjust = "BH", alpha = 0.05)


## Fit the GRMTree model
mos_grmtree <- grmtree(resp ~ sex + age + bmi + Education + depressed +
                       residency + job + multimorbidity + smoker,  
                       data = resp.data,
                       control = grm_control)

## ----eval=FALSE---------------------------------------------------------------
# ## Bonferroni correction
# tree_bonf <- grmtree(response ~ covariate1 + covariate2, data = df,
#                     control = grmtree.control(p_adjust = "bonferroni"))
# 
# ## Hommel
# tree_bh <- grmtree(response ~ covariate1 + covariate2, data = df,
#                   control = grmtree.control(p_adjust = "hommel"))
# 
# ## Holm-Bonferroni
# tree_holm <- grmtree(response ~ covariate1 + covariate2, data = df,
#                     control = grmtree.control(p_adjust = "holm"))

## -----------------------------------------------------------------------------
## Print the tree model
print(mos_grmtree)
print(mos_grmtree, FUN = function(x) " *")

## -----------------------------------------------------------------------------
## Create the regions plot (by default)
plot(mos_grmtree)

## This also creates a regions plot
plot(mos_grmtree, type = "regions",  tnex = 2L)

## Create the histogram plot of the factor scores
plot(mos_grmtree, type = "histogram",  tnex = 2L)

## Create the profile plot with different options
plot(mos_grmtree, type = "profile", tnex = 2L, what = "threshold")
plot(mos_grmtree, type = "profile", tnex = 2L, what = "discrimination")
plot(mos_grmtree, type = "profile", tnex = 2L, what = "item")

## -----------------------------------------------------------------------------
## Return the names of the covariates to know the position of age
names(mos_grmtree$data)

## Rename the age to Age (Uncomment the code below and change to the correct name)
#names(mos_grmtree$data)[3] <- "Age"

## Create the regions plot (by default)
plot(mos_grmtree)

## -----------------------------------------------------------------------------
## Extract and print the threshold parameters
thresholds <- threshpar_grmtree(mos_grmtree)
print(thresholds)

## Extract and print the discrimination parameters
discriminations <- discrpar_grmtree(mos_grmtree)
print(discriminations)

## Extract and print the item parameters
itemspars <- itempar_grmtree(mos_grmtree)
print(itemspars)

