--- title: "Mixed graphical models" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Mixed graphical models} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 6, fig.height = 5) has_cograph <- requireNamespace("cograph", quietly = TRUE) ``` ```{r} library(psychnets) ``` A **mixed graphical model** (`method = "mgm"`) estimates a network over variables of *different types in the same model* -- here continuous (Gaussian) and binary nodes. Each node is regressed on all the others with the L1-penalised GLM that matches its type (linear for continuous, logistic for binary), and the asymmetric estimates are symmetrised by the AND rule. It is equivalent to `mgm::mgm()` for the Gaussian + binary case, and self-certifies via the nodewise GLM residual. ## Building a mixed data set We keep three constructs continuous (`CSU`, `IV`, `SE`) and treat two as binary (`SR`, `TA`) -- as if self-regulation and test anxiety had been recorded as high/low. A small helper dichotomises the binary pair with `dichotomize(method = "rank")` and binds them to the three continuous constructs. ```{r} mixed_scores <- function(x) { d <- as.data.frame(x) b <- dichotomize(d[c("SR", "TA")], method = "rank") data.frame(d[c("CSU", "IV", "SE")], SR = b[, "SR"], TA = b[, "TA"]) } mixed <- mixed_scores(SRL_GPT) head(mixed) ``` ## The fitted network `psychnet()` auto-detects each column's type and fits the matching GLM nodewise: ```{r} fit <- psychnet(mixed, method = "mgm") fit certificate(fit) ``` The edges, and the per-node type and predictability (R-squared for the Gaussian nodes, normalised accuracy `nCC` for the binary ones): ```{r} as.data.frame(fit) net_predict(fit, data = mixed) ``` A binary--binary edge carries the sign of its nodewise-logistic coefficient, which `mgm::mgm()` leaves undefined, so compare such edges on `abs()`. The edge magnitudes otherwise match `mgm::mgm()` closely. ## Plotting Pass the network object to `cograph::splot()` with `psych_styling = TRUE` (green = positive, red = negative); ask for the predictability ring with `predictability = TRUE`. ```{r mgm-plot, eval = has_cograph} cograph::splot(fit, psych_styling = TRUE, predictability = TRUE) ``` `method = "mgm"` (v0.1) supports Gaussian and binary nodes; a multi-level categorical column is rejected with a clear message (one-hot encode it first). See `net_crosswalk("mgm")` for the argument map against `mgm::mgm()`.