3

hoping someone can offer some guidance here.

I'm creating a multivariate simulation using the simDesign package, I am varying the number of factors as well as items that load on each factor. I would like to write a command that identifies the number of factors present in factornumbers and assigns the appropriate items to them (no cross loading). I will be testing all combinations of the conditions below and more, and I would like to have a model command that acknowledge the iterations of differing models, so I don't have to write multiple model statements.

factornumbers<-c(1,2,3,5)
itemsperfactor<-c(5,10,30)

What lavaan and mirt are looking for is below:

mirtmodel<-mirt.model('
                    F1=1-15
                    F2=16-30
                    MEAN=F1,F2
                    COV=F1*F2')

lavmodel <- ' F1=~ Item_1 + Item_2 + Item_3 + Item_4 + Item_5 + Item_6 + Item_7 + Item_8 + Item_9 + Item_10 + Item_11 + Item_12 + Item_13 + Item_14 + Item_15
              F2=~ Item_16 + Item_17 + Item_18 + Item_19 + Item_20 + Item_21 + Item_22 + Item_23 + Item_24 + Item_25 + Item_26 + Item_27 + Item_28 + Item_29 + Item_30'

The simDesign package offers this example, I would like to expand on it but I'm not sure I have the know-how:

lavmodel<-paste0('F=~ ', paste0(colnames(dat)[1L], ' + '),
               paste0(colnames(dat)[-1L], collapse = ' + '))

What I would like is a single mirt and lavaan command that finds the number of factors specified in the factornumbers command and assigns the correct items specified in the data as well as itemsperfactor.

EDIT: I would like the model identification to pick up on which factor & item structure is in use for that condition and fill in the model identification with the correct information.

For Example:

mirtmodel<-mirt.model('
                    F1=1-1
                    F2=6-10
                    F3=11-15
                    F4=16-20
                    F5=21-25
                    MEAN=F1,F2,F3,F4,F5
                    COV=F1*F2*F3*F4*F5')

Or

 mirtmodel<-mirt.model('
                    F1=1-30
                    F2=31-60
                    MEAN=F1,F2
                    COV=F1*F2')

And also the corresponding lavaan models.

navac
  • 87
  • 6
  • "I would like to write a command that identifies the number of factors present in factornumbers and assigns the appropriate items to them (no cross loading)" Isn't this something you know a priori from the `Design` condition inputs? It might be easier if you edit your question to show the types of syntax you are looking for (e.g., 1 factor 10 items versus 2 factor 20 items). – philchalmers Jun 08 '16 at 16:15
  • @philchalmers "Isn't this something you know a priori from the Design condition inputs?" Right, I'm trying to pass the same a priori condition to the model structure. I would like it to recognize it needs a model with 1,2,....n factors and 5,10,30 items depending on which condition is run and do that automatically given the condition inputs. Does that make it any clearer? I've edited in mirt examples, I would be duplicating them in lavaan as well. Thanks for your help. – navac Jun 13 '16 at 22:39

1 Answers1

3

The idea here is to paste different strings together so that the condition input (row of the respective Design object) is all that is required to construct a suitable model specification string. Generating syntax for simulations is arguably the most annoying part of simulations, but at least in R there are a good number of helpful string operations (plus, packages like stringr).

Here's my interpretation of what you are currently looking for using base R functions.

library(SimDesign)
library(mirt)

Design <- createDesign(factornumbers = c(1,2,3,5),
                       itemsperfactor = c(5,10,30))

gen_syntax_mirt <- function(condition){
    fn <- with(condition, factornumbers)
    ipf <- with(condition, itemsperfactor)
    nitems <- fn * ipf
    maxloads <- sort(seq(nitems, ipf, length.out = fn))
    minloads <- c(1, maxloads[-length(maxloads)] + 1)
    fnames <- paste0('F', 1:fn)
    df <- cbind(fnames, ' = ', minloads, '-', maxloads)
    s1 <- apply(df, 1, paste0, collapse = '')
    s2 <- paste0('MEAN = ', paste0(fnames, collapse = ','))
    s3 <- paste0('COV = ', paste0(fnames, collapse = '*'))
    ret <- paste0(c(s1, s2, s3), collapse = '\n')
    mirt.model(ret)
}

gen_syntax_mirt(Design[1,])
gen_syntax_mirt(Design[10,])

The input to this function is a single row from the Design input to runSimulation(), so you can see here that it will work just fine. Do something similar for lavaan's syntax and you'll be set.

philchalmers
  • 727
  • 7
  • 19
  • 1
    "Generating syntax for simulations is arguably the most annoying part of simulations" You can say that again, luckily I'm just about finished. This answer is really straight forward and helpful, I hadn't considered creating objects with them and combining the objects. Very helpful as usual, Phil. Thanks. – navac Jun 20 '16 at 14:41