Search code examples
rfunctionpsych

R simulation function based on psych package not saving values


I'm trying to write a function for R that uses two packages: simsem and psych. In a nutshell, I want the function to allow me to specify a size for each random sample to be drawn using simsem, to specify options for factor analysis (fa) to be run on each sample using psych, and then to save values from the fa model of each sample in a data-frame, so that I can later aggregate across them.

The function, however, is not currently working; no values are being saved in the target data-frame from any of the repetitions of the function.

Reproducible example and my function code below. Really appreciate any insight into what's going awry.

#Install and call simsem and psych package, to simulate datasets based on population model, and fit fa model
install.packages("simsem")
library(simsem)

install.packages("psych")
library(psych)

#Specify Population Model
popModel<-"
f1 =~ 0.7*y1 + 0.7*y2 + 0.7*y3
f2 =~ 0.5*y4 + 0.5*y5 + 0.5*y6
f1 ~~ 1*f1
f2 ~~ 1*f2
f1 ~~ 0.50*f2
y1 ~~ 0.51*y1
y2 ~~ 0.51*y2
y3 ~~ 0.51*y3
y4 ~~ 0.75*y4
y5 ~~ 0.75*y5
y6 ~~ 0.75*y6
"

#Function: User specifies number of reps, sample size, number of factors, rotation and extraction method
#Then for each rep, a random sample of popModel is drawn, a FA model is fit, and two logical values are saved
#in data.frame fit
sample.efa = function(rep, N, nfac, rotation, extract){
 fit = data.frame(RMSEA= logical(0), TLI = logical(0)) #create empty data frame with two columns
 for(i in seq_len(rep)){
    dat = generate(popModel, N) #draw a random sample of N size from popModel
    model = fa(dat, nfactors = nfac, rotate = rotation, fm = extract, SMC = TRUE, alpha = .05) #fit FA model with user specified options from function
    store = data.frame(RMSEA=all(model$rms < .08), TLI = all(model$TLI > .90)) #save two logical values in "store"
names(store) = names(fit) #give "store" same names as target data-frame
    fit=rbind(fit, store) #save values from each iteration of "store" in target data-frame "fit"
  }
}

#Run test of function with small number of reps (5) of sample sizes of 200
set.seed(123)
sample.efa(5, N = 200, nfac = 2, rotation = "promax", extract = "ml")

Solution

  • You changed the names of your dataframe incorrectly...

    sample.efa = function(rep, N, nfac, rotation, extract){
      fit = data.frame(RMSEA= logical(0), TLI = logical(0)) #create empty data frame with two columns
      for(i in seq_len(rep)){
        dat = generate(popModel, N) #draw a random sample of N size from popModel
        model = fa(dat, nfactors = nfac, rotate = rotation, fm = extract, SMC = TRUE, alpha = .05) #fit FA model with user specified options from function
        store = data.frame(RMSEA=all(model$rms < .08), TLI = all(model$TLI > .90)) #save two logical values in "store"
        names(store) = names(fit) #give "store" same names as target data-frame
        fit=rbind(fit, store) #save values from each iteration of "store" in target data-frame "fit"
      }
      return(fit)
    }
    

    Also, you may want to add stringsAsFactors=FALSE to your dataframes to avoid problems later...