mxCI(..., remove = TRUE)

tbates's picture
Category:feature request
Status:by design

Currently users can't remove CIs from models, only add them. Given they can take hours to compute, this can be a hassle.

One way would be to make things like this work:

  model$intervals = NULL
  model$intervals = model$intervals[-3]

An aid to learning would be to add a note to the help about remove = TRUE parameter to mxModel(), which would remove a CI of that name from the model.

newModel = mxModel(oldModel, mxCI("a_r1_c1"), remove = TRUE)


tbates's picture


I guess it might just be more intuitive in the model editing phase to support the equivalent using $




fit_ace <- mxModel(fit_ace, mxCI("top.e_std"), remove=T)

nice to warn when the "removed" item never existed

jpritikin's picture


In term of implementation, I think "model$intervals = NULL" is the easiest. I have a patch for that. However, it's somewhat of a hack because "model$intervals = model$intervals[-3]" doesn't work. Only NULL works. If everybody is okay with that, I'll commit it.

mhunter's picture


Users can remove CIs ... just not the way the op wants

manifests <- names(demoOneFactor)
latents <- c("G")
factorModel <- mxModel("One Factor",
      manifestVars = manifests,
      latentVars = latents,
      mxPath(from=latents, to=manifests),
      mxPath(from=manifests, arrows=2),
      mxPath(from=latents, arrows=2,
            free=FALSE, values=1.0),
      mxData(cov(demoOneFactor), type="cov",
fr <- mxRun(factorModel, intervals=TRUE)
# Ran with no CI because they don't exist
#Add CI
f2 <- mxModel(factorModel, mxCI("A[1,6]"))
f2r <- mxRun(f2, intervals=TRUE)
#Remove CI: f2 has CIs in it but f3 has removed them
f3 <- mxModel(f2, mxCI("A[1,6]"), remove=TRUE)
f3r <- mxRun(f3, intervals=TRUE)

So, are you saying you want the $ accessor to also work for setting and removing CIs?

Also as a note, selection with a negative character has never worked for anything to my knowledge in R.

# fit_ace$intervals[-"top.e_std"]
x <- c(a=7, b=15, g=pi)
x[-"a"] #Fails

tbates's picture


Yeah, having $ set and get work for CIs would be great, IMHO.

tbates's picture


Two issues
1. remove=TRUE doesn't warn the user when the CI doesn't exist (which is misleading),
2. remove = TRUE only works on items specified the same way.

We don't do any redundancy checking, or unpacking CIs into single parameter requests (the way, say that mxPath() effectively does). So

manifests <- names(demoOneFactor)
latents <- c("G")
f1 <- mxModel("One Factor", type="RAM",manifestVars = manifests, latentVars = latents,
      mxPath(from=latents, to=manifests),
      mxPath(from=manifests, arrows=2),
      mxPath(from=latents, arrows=2, free=F, values=1),
      mxData(cov(demoOneFactor), type="cov", numObs=500)
# Add a CI by bracket address
f2 <- mxModel(f1, mxCI("A[1,6]"))
f2 <- mxRun(f2, intervals=T)
# Remove it
f3 <- mxModel(f2, mxCI("A[1,6]"), remove=T)
f3 <- mxRun(f3, intervals=T)
# Add CIs for all cells of A
f4 <- mxModel(f3, mxCI("A"))
f4 <- mxRun(f4, intervals=T)
# Remove CI A[1,6] (one cell of "A")
f5 <- mxModel(f4, mxCI("A[1,6]"), remove=T) # no warning that this was not found
f5 <- mxRun(f5, intervals=T)
summary(f5)$CI # still has A[1,6]
                     lbound  estimate    ubound note
One Factor.A[1,6] 0.3679341 0.3971518 0.4290522     
One Factor.A[2,6] 0.4695034 0.5036607 0.5411646     
One Factor.A[3,6] 0.5389614 0.5772409 0.6193343     
One Factor.A[4,6] 0.6578832 0.7027732 0.7522655     
One Factor.A[5,6] 0.7464224 0.7962494 0.8512582     

We can add the same cell three times, with all being computed (yielding an interesting message in summary)

# Add labels to the free column of A
f2$A$labels[1:6,6] = paste0("A_r", 1:6, "c6") # e.g. A[1,6] = label "A_r1c6"
# then add the same cell to CI list under three different names
f_duplicates <- mxModel(f2, mxCI(c("A", "A[1,6]", "A_r1c6")))
f_duplicates <- mxRun(f_duplicates, intervals = T)
     lbound  estimate    ubound note
1 0.3679341 0.3971518 0.4290522     
2 0.3679341 0.3971518 0.4290522     
3 0.4695034 0.5036607 0.5411646     
4 0.5389614 0.5772409 0.6193343     
5 0.6578832 0.7027732 0.7522655     
6 0.7464224 0.7962494 0.8512582     
7 0.3679341 0.3971518 0.4290522     
# Warning message:
#In data.row.names(row.names, rowsi, i) :
#  some row.names duplicated: 7 --> row.names NOT used

Row names not always lost

f_duplicates <- mxModel(f2, mxCI(c("A[1,6]", "A_r1c6")))
f_duplicates <- mxRun(f_duplicates, intervals = T)
                     lbound  estimate    ubound note
One Factor.A[1,6] 0.3679341 0.3971518 0.4290522     
A_r1c6            0.3679341 0.3971518 0.4290522     

tbates's picture


I think implementing allowing $intervals = NULL would be a good way forward here. Most cases where the user wants to remove a CI, they can then get what they want either with mxModel and remove = T, or just NULLing out intervals and starting over.

PS: the current error doesn't reflect what the user asked to do: mxModel(model, intervals) won't work, and this would apply to many things accessed via $, like matrices, algebras, constraints, etc.

f2r$intervals = NULL
Error: I'm very sorry, but direct modification of objects inside an mxModel is not supported. The recommended approach to modifying an mxMatrix, mxAlgebra or other object within a model is to rebuild the mxModel. So, for example, 'model <- mxModel(model, Something)' can be used to replace Something inside the model, instead of 'model$Something <- Something' which does not work

jpritikin's picture


I agree this is annoying, but I did add some examples of removal to the mxCI man page. Here is an easy-ish way to remove all intervals:

model <- mxModel(model, remove=TRUE, model$intervals)

AdminRobK's picture


Although we don't support users using the @ accessor, the following would also work:

model@intervals <- list()

tbates's picture


Could close this with model@intervals <- list() as the work-around.

tbates's picture


Status:active» by design

good work arounds available, and documented