# constraining item difficulty in 2PL estimation using “ltm”

I was planning to bridge IRT estimations of different tests using one particular item as an anchor. Currently, I am using the ltm package in R and am planning to do it using the option constraint under the function ltm().

According to the documentation, this can be done as below:

The two-parameter logistic model for the WIRS data with the constraint that (i) the easiness parameter for the 1st item equals 1 and (ii) the discrimination parameter for the 6th item equals -0.5

ltm(WIRS ~ z1, constr = rbind(c(1, 1, 1), c(6, 2, -0.5)))


After running the line above, it occurs to me that the difficulty parameter seems not to be constrained as specified: while difficulty of Item 1 is expected to be 1, it is estimated as -0.070. (On the other hand, the discrimination parameter estimation behaved as expected)

Call:
ltm(formula = WIRS ~ z1, constraint = rbind(c(1, 1, 1), c(6, 2, -0.5)))
Coefficients:
Dffclt  Dscrmn
Item 1  -0.070  14.259
Item 2   0.121  -0.918
Item 3   3.901   0.225
Item 4  -4.267  -0.296
Item 5   2.374   0.223
Item 6   3.384   0.500
Log.Lik: -3583.093


Am I misunderstanding this functionality, and, are there any other recommended ways to set up similar constraints for IRT estimates?

Note that ltm provides report for two different item parameterizations (for simplicity I focus on the case of one latent variable $z$; refer to the help page for detailed description):

$$logit(\pi_i)= \beta_{0i} + \beta_{1i}z \quad (1)$$ and $$logit(\pi_i)= a_{i}(z-b_{i}) \quad (2)$$

The estimation (and thereby parameter constraining) is based exclusively on the parameterization in Eqn (1). That is, using ltm(..., constraint = rbind(c(1, 1, 1), ...)) the intercept $\beta_{0i}$ is set to 1.

Parameter reporting is done via the print-, summary- and coef-methods. The reported parameterization is chosen by the optional argument IRT.param. (Unfortunately,) in case of one (non-exponentiated) latent variable the reported parameters are in line with the parameterization in Eqn (2) by default. Note that there is a simple transformation for the easiness/difficulty parameters (discriminiation parameters are the same):

$$b_{i} = -\beta_{01}/\beta_{1i}$$

> mod <- ltm(WIRS ~ z1, constr = rbind(c(1, 1, 1), c(6, 2, -0.5)))
> (c1 <- coef(mod))
Dffclt     Dscrmn
Item 1 -0.07013311 14.2586015
Item 2  0.12084500 -0.9178884
Item 3  3.90054017  0.2245981
Item 4 -4.26713242 -0.2957836
Item 5  2.37431636  0.2226061
Item 6  3.38428725  0.5000000
> (c2 <- mod\$coefficients)
(Intercept)         z1
Item 1   1.0000000 14.2586015
Item 2   0.1109222 -0.9178884
Item 3  -0.8760541  0.2245981
Item 4  -1.2621480 -0.2957836
Item 5  -0.5285374  0.2226061
Item 6  -1.6921436  0.5000000
> head(cbind(-c2[, 1]/c2[, 2], c2[, 2]), 1)
[,1]    [,2]
Item 1 -0.07013311 14.2586


The standard errors of the constrained item parameters are NA

> summary(mod)

Call:
ltm(formula = WIRS ~ z1, constraint = rbind(c(1, 1, 1), c(6,
2, -0.5)))

...

Coefficients:
value std.err   z.vals
Dffclt.Item 1 -0.0701      NA       NA
Dffclt.Item 2  0.1208  0.0787   1.5346
Dffclt.Item 3  3.9005  1.5996   2.4385
Dffclt.Item 4 -4.2671  1.7235  -2.4758
Dffclt.Item 5  2.3743  0.9179   2.5868
Dffclt.Item 6  3.3843  0.0166 203.7598
Dscrmn.Item 1 14.2586  9.2778   1.5369
Dscrmn.Item 2 -0.9179  0.1125  -8.1613
Dscrmn.Item 3  0.2246  0.0953   2.3574
Dscrmn.Item 4 -0.2958  0.1072  -2.7593
Dscrmn.Item 5  0.2226  0.0904   2.4631
Dscrmn.Item 6  0.5000      NA       NA

...


I agree that this behaviour is unexpected (and might even be unintended). A bug report might be useful.

About the recommended ways for test equating

There are several common ways to equate different tests, for example:

1. item parameter constraining (also possible in the R packages TAM and mirt),
2. common calibration of both tests and
3. item parameter transformation e.g. via mean-mean-linking (cf., R package plink).