umxGxE: umxGxE: Implements ACE models with moderation of paths, e.g....

View source: R/umx_build_umxGxE.R

umxGxER Documentation

umxGxE: Implements ACE models with moderation of paths, e.g. by SES.

Description

Make a 2-group GxE (moderated ACE) model (Purcell, 2002). GxE interaction studies test the hypothesis that the strength of genetic (or environmental) influence varies parametrically (usually linear effects on path estimates) across levels of environment. umxGxE allows detecting, testing, and visualizing G xE (or C or E x E) interaction forms.

Usage

umxGxE(
  name = "G_by_E",
  selDVs,
  selDefs,
  dzData,
  mzData,
  sep = NULL,
  data = NULL,
  zyg = "zygosity",
  digits = 3,
  lboundACE = NA,
  lboundM = NA,
  dropMissingDef = TRUE,
  dzAr = 0.5,
  dzCr = 1,
  autoRun = getOption("umx_auto_run"),
  tryHard = c("no", "yes", "ordinal", "search"),
  optimizer = NULL,
  selCovs = NULL
)

Arguments

name

The name of the model (default= "G_by_E")

selDVs

The dependent variable (e.g. "IQ")

selDefs

The definition variable (e.g. "SES")

dzData

The DZ dataframe containing the Twin 1 and Twin 2 DV and moderator (4 columns)

mzData

The MZ dataframe containing the Twin 1 and Twin 2 DV and moderator (4 columns)

sep

How to expand selDVs into full names, i.e., "_T" makes "var" -> "var_T1" and "var_T2"

data

If provided, dzData and mzData are treated as valid levels of zyg to select() data sets (default = NULL)

zyg

If data provided, this column is used to select rows by zygosity (Default = "zygosity")

digits

Rounding precision for tables (default 3)

lboundACE

If not NA, then lbound the main effects at this value (default = NA, can help to set this to 0)

lboundM

If not NA, then lbound the moderator effects at this value (default = NA, can help to set this to 0)

dropMissingDef

Whether to automatically drop missing def var rows for the user (default = TRUE). You get a polite note.

dzAr

The DZ genetic correlation (defaults to .5, vary to examine assortative mating).

dzCr

The DZ "C" correlation (defaults to 1: set to .25 to make an ADE model).

autoRun

Optionally run the model (default), or just to create it and return without running.

tryHard

Optionally tryHard to get the model to converge (Default = 'no'). "yes" uses mxTryHard. Other options: "ordinal", "search".

optimizer

Optionally set the optimizer (default NULL does nothing)

selCovs

(optional) covariates to include in the means model (do not include sep in names)

Details

Paths are linear in the moderator \(M\): \(a_i = a + a_m M\) (and likewise for \(c\), \(e\)). Estimated main effects (a, c, e) and moderation slopes (am, cm, em) live on the top submodel.

The following figure shows the GxE model as a path diagram:

Figure: GxE.png

Value

  • GxE OpenMx::mxModel()

Synthetic data and recovery checks

For benchmarking and teaching, generate wide twin data with known Purcell paths via umx_make_GxE_data(). That helper returns a data frame ready for umxGxE (columns zygosity, outcome_T*, outcomeAge_T*, mod_T*, age_T*) plus attribute "truth" with the generative parameters. The attribute is ignored by fitting; use it only to compare estimates to ground truth, e.g. attr(df, "truth")$am.

Defaults in the simulator: \(a=0.50\), \(c=0.30\), \(e=0.60\), \(a_m=0.15\), \(c_m=e_m=0\). Two phenotypes share the same latent ACE draws:

outcome

Pure GxE (no age mean effect). Fit with selDVs = "outcome", selDefs = "mod".

outcomeAge

Same residuals plus a mean effect of age (target correlation of approximately 0.2 with age). Fit with selDVs = "outcomeAge", selDefs = "mod", selCovs = "age".

Moderator and age are shared within family by default (mod_T1 == mod_T2, age_T1 == age_T2).

Power: Moderated ACE is low-powered. Even with thousands of pairs, recovery of \(a_m\) is noisy; large absolute error relative to the true slope is expected in single replications. Prefer tryHard = "yes", adequate \(N\), and simulation studies rather than one-shot recovery demos.

References

Purcell, S. (2002). Variance components models for gene-environment interaction in twin analysis. Twin Research, 6, 554-571. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1375/twin.5.6.554")}

See Also

umx_make_GxE_data(), umxGxE_window(), umxReduce(), umxSummary()

Other Twin Modeling Functions: power.ACE.test(), umx, umxACE(), umxACE_DE(), umxACE_GLM(), umxACEcov(), umxACEv(), umxCP(), umxCloud(), umxDiffMZ(), umxDiscTwin(), umxDoC(), umxDoCp(), umxGxE_window(), umxGxEbiv(), umxIP(), umxMRDoC(), umxReduce(), umxReduceACE(), umxReduceGxE(), umxRotate.MxModelCP(), umxSexLim(), umxSimplex(), umxSummarizeTwinData(), umxSummaryACE(), umxSummaryACE_GLM(), umxSummaryACEv(), umxSummaryDoC(), umxSummaryGxEbiv(), umxSummarySexLim(), umxSummarySimplex(), umxTwinMaker(), umx_make_double_entry_data()

Examples

## Not run: 
require(umx)
data(twinData)
twinData$age1 = twinData$age2 = twinData$age
selDVs  = "bmi"
selDefs = "age"
mzData  = subset(twinData, zygosity == "MZFF")[1:100,]
dzData  = subset(twinData, zygosity == "DZFF")[1:100,]
m1 = umxGxE(selDVs= "bmi", selDefs= "age", sep= "", dzData= dzData, mzData= mzData, tryHard= "yes")

# Select the data on the fly with data= and zygosity levels
m1 = umxGxE(selDVs= "bmi", selDefs= "age", sep="", dzData= "DZFF", mzData= "MZFF", data= twinData)

# ===============================================================
# = example with Twins having different values of the moderator =
# ===============================================================

twinData$age1 = twinData$age2 = twinData$age
tmp = twinData
tmp$age2 = tmp$age2 +rnorm(n=length(tmp$age2))
selDVs  = "bmi"
selDefs = "age"
mzData = subset(tmp, zygosity == "MZFF")
dzData = subset(tmp, zygosity == "DZFF")
m1 = umxGxE(selDVs= "bmi", selDefs= "age", sep= "", dzData= dzData, mzData= mzData, tryHard= "yes")

# ====================================
# = Controlling output of umxSummary =
# ====================================
umxSummaryGxE(m1)
umxSummary(m1, location = "topright")
umxSummary(m1, separateGraphs = TRUE)

# # Test dropping moderation on a path
m2 = umxModify(m1, regex = "am_.*", comparison = TRUE, tryHard = "yes")

# umxReduce knows how to test all relevant hypotheses for GxE models,
# reporting these in a nice table.
umxReduce(m1)

# ============================================================
# = Synthetic ground-truth data: umx_make_GxE_data + umxGxE =
# ============================================================
# Generate N pairs with known a, c, e, am (see attr(df, "truth"))
df = umx_make_GxE_data(nMZpairs = 800, nDZpairs = 800, seed = 1)
truth = attr(df, "truth")
truth[c("a", "c", "e", "am", "cm", "em")]

# Pure GxE phenotype (no age in means)
mGxE = umxGxE(selDVs = "outcome", selDefs = "mod", sep = "_T",
  data = df, mzData = "MZ", dzData = "DZ", tryHard = "yes")
c(est_am = mGxE$top$am$values[1, 1], true_am = truth$am)

# Same latents + age mean effect via selCovs
mAge = umxGxE(selDVs = "outcomeAge", selDefs = "mod", selCovs = "age",
  sep = "_T", data = df, mzData = "MZ", dzData = "DZ", tryHard = "yes")

# Custom generative slopes (e.g. null am, nonzero em)
df2 = umx_make_GxE_data(nMZpairs = 500, nDZpairs = 500,
  am = 0, em = 0.10, seed = 2)
attr(df2, "truth")[c("am", "em")]

## End(Not run)

umx documentation built on Oct. 11, 2026, 5:07 p.m.