difPolyLogistic: Logistic regression DIF statistics for polytomous (ordinal)...

difPolyLogisticR Documentation

Logistic regression DIF statistics for polytomous (ordinal) items

Description

Computes DIF detection using logistic regression models for ordinal (polytomous) items.

Usage

difPolyLogistic(Data, group, focal.name, anchor = NULL, member.type = "group",
match = "score", type = "both", criterion = "LRT", alpha = 0.05, all.cov=FALSE,
purify = FALSE, nrIter = 10, p.adjust.method = NULL, save.output = FALSE,
output = c("out", "default"))

Arguments

Data

a data frame or matrix: one row per respondent, one column per item. Items must be coded as ordinal variables.

group

a vector or column index/name from Data: specifies group membership.

focal.name

the label identifying the focal group (ignored if member.type = "cont").

anchor

a vector of column indices or names specifying anchor (non-DIF) items. If NULL and purify = FALSE, all items are used as anchors. Ignored if match is not "score".

member.type

"group" (default) if group is categorical; "cont" if group is continuous.

match

matching criterion. Use "score" for test score, "restscore" for item-excluded score, or provide an external continuous/discrete vector.

type

DIF type to test: "both" (default), "udif" (uniform DIF only), or "nudif" (non-uniform DIF only).

criterion

test statistic: "LRT" (default) for likelihood ratio test or "Wald" for Wald test.

alpha

significance level for DIF detection (default = 0.05).

all.cov

logical: whether to return full covariance matrices of the parameter estimates. Default is FALSE.

purify

logical: whether to apply iterative purification to refine anchor items (default = FALSE). Requires match = "score".

nrIter

maximum number of iterations for purification (default = 10).

p.adjust.method

method for p-value adjustment across items (e.g., "BH", "bonferroni"). Default = NULL.

save.output

logical: if TRUE, saves output to a text file.

output

character vector: output\[1] is the filename (without extension), output\[2] is the directory path (or "default" for working directory).

Details

The function fits cumulative ordinal logistic regression models (via VGAM::vglm) to detect DIF in polytomous items.

Three nested models are fit per item and compared to assess DIF:

  • M_0: No DIF (only match effect)

  • M_1: Uniform DIF (match + group)

  • M_2: Uniform + non-uniform DIF (match + group + interaction)

M_0, M_1, and M_2 are compared using either likelihood-ratio or Wald tests, depending on the criterion argument.

When match = "restscore", the matching variable is defined as the sum score excluding the item being tested.

When purify = TRUE, the algorithm iteratively refines the anchor set by excluding detected DIF items and updating scores.

This function handles both group-based DIF (member.type = "group") and DIF based on continuous moderators (member.type = "cont").

For each item, the DIF analysis is performed using only complete cases. Respondents with missing data on the item being tested, the matching variable, or the group variable are excluded from the estimation for that item.

For very strong predictors (e.g., matching variables that nearly perfectly separate response categories), the underlying ordinal regression models may become numerically unstable. This can result in extreme coefficients, saturation warnings, and possibly negative pseudo-R² values. These cases reflect data properties rather than programming errors.

Value

Returns an object of class "Logistic", a list with elements:

LogistikPoly

numeric vector of DIF test statistics for each item.

p.value

p-values associated with each test statistic.

logitPar

matrix of estimated parameters for best-fitting models (per item).

logitSe

matrix of standard errors for logitPar.

parM0, seM0

parameter estimates and SEs for the null model (no DIF).

cov.M0, cov.M1

covariance matrices for null and full models (if all.cov = TRUE).

deltaR2

effect sizes (McKelvey & Zavoina R^2) per item.

alpha, thr

alpha value and corresponding statistical threshold.

DIFitems

indices of items detected as DIF (or "No DIF item detected").

type, criterion, match, member.type

echoed inputs.

p.adjust.method, adjusted.p

if adjustment requested, adjusted p-values and method used.

purification, nrPur, difPur, convergence

details of the purification process.

names, anchor.names

item names and anchor items used.

save.output, output

output options echoed.

Author(s)

Sebastien Beland
Faculte des sciences de l'education
Universite de Montreal (Canada)
sebastien.beland@umontreal.ca

References

Zumbo, B. D. (1999). A Handbook on the Theory and Methods of Differential Item Functioning (DIF): Logistic Regression Modeling as a Unitary Framework for Binary and Likert-Type (Ordinal) Item Scores. Ottawa, ON: Department of National Defense.

Zumbo, B. D. & Thomas, D. R. (1997). A measure of effect size for a model-based approach for studying DIF. Educational and Psychological Measurement, 57(4), 679-688.

See Also

LogistikPoly, VGAM::vglm

Examples

## Not run: 

# With real data

data(SCS)

# Without item purification
difPolyLogistic(SCS[,1:10], group=SCS[,11], 
focal.name = "1", purify=FALSE)  

# Without item purification and the rest score
difPolyLogistic(SCS[,1:10], group=SCS[,11], 
focal.name = "1", purify=FALSE,, match = "restscore") 

# With item purification
difPolyLogistic(SCS[,1:10], group=SCS[,11], 
focal.name = "1", purify=TRUE)

# With item purification
difPolyLogistic(SCS[,1:10], group=SCS[,11], 
focal.name = "1", purify=TRUE)

# With item purification with LRT criterion
difPolyLogistic(SCS[,1:10], group=SCS[,11], 
focal.name = "1", purify=TRUE, criterion = "LRT") 

# With item purification with LRT criterion and alpha = 0.01
difPolyLogistic(SCS[,1:10], group=SCS[,11], 
focal.name = "1", purify=TRUE, criterion = "LRT", alpha = 0.01) 

# With simulated data

set.seed(1234)

# original item parameters
a <- rlnorm(10, -0.5)  # slopes
b <- runif(10, -2, 2)  # difficulty
d <- list()
d[[1]] <- c(0, 2, .5, -.15, -1.1)
d[[2]] <- c(0, 2, .25, -.45, -.75)
d[[3]] <- c(0, 1, .5, -.65, -1)
d[[4]] <- c(0, 2, .5, -.85, -2)
d[[5]] <- c(0, 1, .25, -.05, -1)
d[[6]] <- c(0, 2, .5, -.95, -1)
d[[7]] <- c(0, 1, .25, -.35, -2)
d[[8]] <- c(0, 2, .5, -.15, -1)
d[[9]] <- c(0, 1, .25, -.25, -2)
d[[10]] <- c(0, 2, .5, -.35, -1)

# Uniform DIF
It <- 10; NR <- 1000; NF <- 1000
ItDIFa <- NULL; Ga <- NULL
ItDIFb <- c(1, 3)
Gb <- rep(.5, 2)

Out.Unif <- SimPolyDif(It, ItDIFa, ItDIFb, NR, NF, a, b, d,
                       ncat = 5, Ga = Ga, Gb = Gb)
Out.Unif$ipars
Data <- Out.Unif$data

# Without item purification
difPolyLogistic(Out.Unif$data[,1:10], group=Out.Unif$data[,11], 
focal.name = "G1", purify=FALSE)  

# Without item purification and restscore
difPolyLogistic(Out.Unif$data[,1:10], group=Out.Unif$data[,11], 
focal.name = "G1", purify=FALSE, match = "restscore")  

# With item purification
difPolyLogistic(Out.Unif$data[,1:10], group=Out.Unif$data[,11], 
focal.name = "G1", purify=TRUE) 

# With item purification with LRT criterion
difPolyLogistic(Out.Unif$data[,1:10], group=Out.Unif$data[,11], 
focal.name = "G1", purify=TRUE, criterion = "LRT") 

# With item purification with LRT criterion and alpha = 0.01
difPolyLogistic(Out.Unif$data[,1:10], group=Out.Unif$data[,11], 
focal.name = "G1", purify=TRUE, criterion = "LRT", alpha = 0.01)  

# We implemented a specific S3 plot method: plot.Logistic. It can be used as follows

res <- difPolyLogistic(Out.Unif$data[,1:10], group=Out.Unif$data[,11], 
focal.name = "G1", purify=FALSE)
plot.Logistic(res)

 
## End(Not run)
 

difR documentation built on June 8, 2025, 1:03 p.m.