ecmerkle/blavaan

allow.empty.cell = TRUE maybe incomplete

Closed this issue · 10 comments

I'm getting:

Error in SC.TH[, th.idx] <- scores[, fit$th.idx, drop = FALSE] : 
  number of items to replace is not a multiple of replacement length
Calls: blavaan ... lav_samplestats_from_data -> muthen1984 -> lav_samplestats_step1

For the following script:

library(blavaan)
NoYesLevels <- c('No','Not sure','Yes')
EuphoricLevels <- c('Euphoric', 'Mildly euphoric', 'No change', 'Mild discomfort', 'Sever
e discomfort')
ImpactLevels <- c('Helped','Slightly helped','No impact','Slightly hindered','Hindered')
AbsItemNames <- c('boredom','frustration','anxiety', 'abort','bodyAcute','bodyAfter','sle
ep')

ImportStudyItems <- function(df) {
  if (any(is.na(match(AbsItemNames, colnames(df))))) stop("Items are mising")
  
  df[['boredom']] <- ordered(df[['boredom']], levels=NoYesLevels)
  df[['frustration']] <- ordered(df[['frustration']], levels=NoYesLevels)
  df[['anxiety']] <- ordered(df[['anxiety']], levels=NoYesLevels)
  df[['abort']] <- ordered(df[['abort']], levels=NoYesLevels)
  df[['bodyAcute']] <- ordered(df[['bodyAcute']], levels=EuphoricLevels)
  df[['bodyAfter']] <- ordered(df[['bodyAfter']], levels=EuphoricLevels)
  df[['sleep']] <- ordered(df[['sleep']], levels=ImpactLevels)
  df
}

psiData <- ImportStudyItems(read.csv("psi.csv"))
pmData <- ImportStudyItems(read.csv("pm.csv"))
combinedData <- rbind(cbind(psiData, group="psi"),
                      cbind(pmData, group="pm"))
combinedData$group <- factor(combinedData$group)

spec <- '
phenom =~ boredom + frustration + anxiety + abort + bodyAcute + bodyAfter + sleep

boredom ~ 1
frustration ~ 1
anxiety ~ 1
abort ~ 1
bodyAcute ~ 1
bodyAfter ~ 1
sleep ~ 1
phenom ~ c(0, NA)*1

phenom ~~ 1*phenom
boredom ~~ v1*boredom
frustration ~~ v2*frustration
anxiety ~~ v3*anxiety
abort ~~ v4*abort
bodyAcute ~~ v5*bodyAcute
bodyAfter ~~ v6*bodyAfter
sleep ~~ v7*sleep

boredom | -.43*t1 + .43*t2
frustration | -.43*t1 + .43*t2
anxiety | -.43*t1 + .43*t2
abort | -.43*t1 + .43*t2
bodyAcute | -.84*t1 + -.25*t2 + .25*t3 + .84*t4
bodyAfter | -.84*t1 + -.25*t2 + .25*t3 + .84*t4 
sleep | -.84*t1 + -.25*t2 + .25*t3 + .84*t4
'
fit <- blavaan(spec, data=combinedData,
               n.chains = 2, sample=500,
               ordered = AbsItemNames,
               group = "group",
               group.equal = c("loadings", "intercepts", "regressions"),
               std.lv=TRUE, allow.empty.cell = TRUE)
summary(fit)

Sample data files are attached:
pm.csv
psi.csv

Thanks! Will look at this soon...

This is working for me. I am wondering whether you are using the github version of lavaan here. The allow.empty.cell functionality required a PR to lavaan as well as a change to blavaan.

Sorry, I spoke too soon. I didn't realize you updated the data files!

It seems to work if you add the argument cat.wls.w = FALSE to the blavaan() command. I will send another PR to lavaan once I figure out the implications of that argument. (but I am nearly certain that the argument is irrelevant to blavaan)

I confirm that cat.wls.w = FALSE solves the problem for these data. Thanks! I will continue testing.

Thanks, I just set cat.wls.w = FALSE for all blavaan models because it has no impact on blavaan. Maybe there is still something to do in lavaan if someone wants to use allow.empty.cell there, though I am not sure it makes sense to do maximum likelihood estimation here. I also saw your other comment from the closed issue and will get to that soon.

I also saw your other comment from the closed issue and will get to that soon.

Don't bother. The report is the same. I opened a new issue because I wasn't sure whether you saw the comment in the closed issue.

Here's a potentially new, related issue. After the chains finish sampling, I'm getting:

Computing post-estimation metrics (including lvs if requested)...
Warning messages:
1: In TH[[i]][exidx] <- fit$theta[fit$th.idx] :
  number of items to replace is not a multiple of replacement length
2: In TH[[i]][exidx] <- fit$theta[fit$th.idx] :
  number of items to replace is not a multiple of replacement length

I'm including the script and data again because maybe the data is different:

library(rstan)
options(mc.cores = parallel::detectCores()/2)
library(blavaan)

NoYesLevels <- c('No','Not sure','Yes')
EuphoricLevels <- c('Euphoric', 'Mildly euphoric', 'No change', 'Mild discomfort', 'Severe discomfort')
ImpactLevels <- c('Helped','Slightly helped','No impact','Slightly hindered','Hindered')
AbsItemNames <- c('boredom','frustration','anxiety', 'abort','bodyAcute','bodyAfter','sleep')

ImportStudyItems <- function(df) {
  if (any(is.na(match(AbsItemNames, colnames(df))))) stop("Items are mising")
  
  df[['boredom']] <- ordered(df[['boredom']], levels=NoYesLevels)
  df[['frustration']] <- ordered(df[['frustration']], levels=NoYesLevels)
  df[['anxiety']] <- ordered(df[['anxiety']], levels=NoYesLevels)
  df[['abort']] <- ordered(df[['abort']], levels=NoYesLevels)
  df[['bodyAcute']] <- ordered(df[['bodyAcute']], levels=EuphoricLevels)
  df[['bodyAfter']] <- ordered(df[['bodyAfter']], levels=EuphoricLevels)
  df[['sleep']] <- ordered(df[['sleep']], levels=ImpactLevels)
  df
}

psiData <- ImportStudyItems(read.csv("psi.csv"))
pmData <- ImportStudyItems(read.csv("pm.csv"))
combinedData <- rbind(cbind(psiData, group="psi"),
                      cbind(pmData, group="pm"))
combinedData$group <- factor(combinedData$group)

spec <- '
phenom =~ boredomL*boredom + frustrationL*frustration + anxietyL*anxiety + abortL*abort + bodyAcuteL*bodyAcute + bodyAfterL*bodyAfter + sleepL*sleep

boredom ~ boredomM*1
frustration ~ frustrationM*1
anxiety ~ anxietyM*1
abort ~ abortM*1
bodyAcute ~ bodyAcuteM*1
bodyAfter ~ bodyAfterM*1
sleep ~ sleepM*1
phenom ~ c(0, pmM)*1

phenom ~~ 1*phenom
boredom ~~ boredomVar*boredom
frustration ~~ frustrationVar*frustration
anxiety ~~ anxietyVar*anxiety
abort ~~ abortVar*abort
bodyAcute ~~ bodyAcuteVar*bodyAcute
bodyAfter ~~ bodyAfterVar*bodyAfter
sleep ~~ sleepVar*sleep

boredom | -.431*t1 + .431*t2
frustration | -.431*t1 + .431*t2
anxiety | -.431*t1 + .431*t2
abort | -.431*t1 + .431*t2
bodyAcute | -.842*t1 + -.253*t2 + .253*t3 + .842*t4
bodyAfter | -.842*t1 + -.253*t2 + .253*t3 + .842*t4
sleep | -.842*t1 + -.253*t2 + .253*t3 + .842*t4
'
fit <- blavaan(spec, data=combinedData,
               n.chains = 2,
               ordered = AbsItemNames,
               dp = dpriors(nu = "normal(0,1)", alpha="normal(0,2)", lambda="normal(0,5)"),
               group = "group",
               group.equal = c("loadings", "intercepts", "regressions"),
               std.lv=TRUE, allow.empty.cell = TRUE, cat.wls.w = FALSE)

pm.csv
psi.csv

Here's another example with a more severe error:

Computing post-estimation metrics (including lvs if requested)...
Error : Exception: mismatch in dimension declared and found in context; processing stage=data initialization; variable name=u15; position=1; dims declared=(2,20); dims found=(2,21) (in 'stanmarg', line 683, column 2 to column 52)
In addition: There were 39 warnings (use warnings() to see them)
failed to create the sampler; sampling not done
Computing post-estimation metrics (including lvs if requested)...
Stan model 'stanmarg' does not contain samples.
Error in rowvec[samppar] <- which(grepl(stanvec[j], names(b.est)) & !(grepl("_c\\[",  : 
  replacement has length zero
Calls: blavaan -> coeffun_stanmarg
Execution halted

See data attached here:
pm.csv
psi.csv

I just sent blavaan 0.5-6 to CRAN, and my PR to lavaan with allow.empty.cell updates was accepted. So I am closing these issues, but please reopen if something arises.