tbates / umx

Making Structural Equation Modeling (SEM) in R quick & powerful
https://tbates.github.io/
44 stars 17 forks source link

umxSuperModel: handle nesting better #221

Open lf-araujo opened 10 months ago

lf-araujo commented 10 months ago

Super models with nested submodels are handled up to two, but no more:

     data(docData)

     mzData  = subset(docData, zygosity %in% c("MZFF", "MZMM")) |>
       dplyr::mutate(ethnicity = rep(LETTERS[1:5],140))

     dzData  = subset(docData, zygosity %in% c("DZFF", "DZMM")) |>
       dplyr::mutate(ethnicity = rep(LETTERS[1:5],140))

     # ============================
     # = 2. Make a MRDoC2 model   =
     # ============================

 outa <- umxMRDoC(name = "a", pheno = c("varA1", "varA2"), prss = c("varB1", "varA3") ,
                     mzData = mzData|>dplyr::filter(ethnicity=="A"),
       dzData = dzData|>dplyr::filter(ethnicity=="A")) |>
      umxModify( regex="*", newlabels ="a_\\1" ,  autoRun = F)

 outb <- umxMRDoC(name = "b", pheno = c("varA1", "varA2"), prss = c("varB1", "varA3") ,
                     mzData = mzData|>dplyr::filter(ethnicity=="B"),
       dzData = dzData|>dplyr::filter(ethnicity=="B")) |>
      umxModify( regex="*", newlabels ="b_\\1" ,  autoRun = F)

 outc <- umxMRDoC(name = "c", pheno = c("varA1", "varA2"), prss = c("varB1", "varA3") ,
                     mzData = mzData|>dplyr::filter(ethnicity=="C"),
       dzData = dzData|>dplyr::filter(ethnicity=="C")) |>
      umxModify( regex="*", newlabels ="c_\\1" ,  autoRun = F)

multi <- umxSuperModel("multigroup", outa, outb)

# THIS WORKS!, NOW:

multi <- umxSuperModel("multigroup", outa, outb, outc)

# doesn't
#  There is already a model named 'top_2'

The issue lies at the underlying renaming functionality, that is only checking up to two submodels.

tbates commented 10 months ago

In umxSuperModel snippet (below) , or should this be a request to enhance OpenMx::mxRename?

tmpnames = umxModelNames(newModel)
dupes = tmpnames[duplicated(tmpnames)] # "top" "MZ" "DZ"
if(length(dupes) > 0){
    suffix = 2
    subNames = names(newModel$submodels)[-1]
    for(thisSub in subNames){
        thisModel = newModel$submodels[[thisSub]]
        for(thisDupName in dupes){
            thisModel = mxRename(thisModel, paste0(thisDupName, "_", suffix), oldname = thisDupName)
        }
        newModel = mxModel(newModel, thisModel)
        suffix = suffix + 1
    }
lf-araujo commented 9 months ago

The issue is in the excerpt above, when the innermost for loop is run, if there is more than 2 models, suffix will not have increased and mxRename will complain. There is an ugly solution:

move up suffix = suffix + 1 to the innermost loop, three lines up. Which will result in:

> umxModelNames(multi)
 [1] "a"        "b"        "c"        "top"      "topMZ"    "topDZ"    "top_2"    "topMZ_3" 
 [9] "topDZ_4"  "top_8"    "topMZ_9"  "topDZ_10"

Still thinking in something more elegant.

tbates commented 9 months ago

I'll have a look

lf-araujo commented 9 months ago

Thanks.

I see that sometimes the starting values for the thresholds are not always ascending, not sure that this is what is causing this issue. Luis Araujo T32 | Virginia Institute for Psychiatric and Behavioral Genetics | Richmond | US Department of Psychiatry | The University of Melbourne | AU +1 804 502-4074 (tel:+1%20804%20502-4074) http://go.unimelb.edu.au/y5yr

On Oct 4 2023, at 5:09 am, Tim Bates @.***> wrote:

I'll have a look — Reply to this email directly, view it on GitHub (https://github.com/tbates/umx/issues/221#issuecomment-1746457579), or unsubscribe (https://github.com/notifications/unsubscribe-auth/ACNLSLTGMCWAHBNSDZA6CWTX5URUVAVCNFSM6AAAAAA4PBYEQOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONBWGQ2TONJXHE). You are receiving this because you authored the thread.