Title: | Latent Variable Network Modeling |
---|---|
Description: | Estimate, fit and compare Structural Equation Models (SEM) and network models (Gaussian Graphical Models; GGM) using OpenMx. Allows for two possible generalizations to include GGMs in SEM: GGMs can be used between latent variables (latent network modeling; LNM) or between residuals (residual network modeling; RNM). For details, see Epskamp, Rhemtulla and Borsboom (2017) <doi:10.1007/s11336-017-9557-x>. |
Authors: | Sacha Epskamp |
Maintainer: | Sacha Epskamp <[email protected]> |
License: | GPL-2 |
Version: | 0.3.5 |
Built: | 2024-11-13 06:41:34 UTC |
Source: | CRAN |
This function minimizes the Extended Bayesian Information Criterion (EBIC; Chen and Chen, 2008) to choose the lvglasso tuning parameter. See lvglasso
EBIClvglasso(S, n, nLatents, gamma = 0.5, nRho = 100, lambda, ...)
EBIClvglasso(S, n, nLatents, gamma = 0.5, nRho = 100, lambda, ...)
S |
Sample variance-covariance matrix |
n |
Sample Size |
nLatents |
Number of latent variables |
gamma |
EBIC hyper-parameter |
nRho |
Number of tuning parameters to test |
lambda |
The lambda argument containing factor loadings, only used for starting values! |
... |
Arguments sent to |
The optimal result of lvglasso
, with two more elements:
rho |
The selected tuning parameter |
ebic |
The optimal EBIC |
Sacha Epskamp <[email protected]>
Chen, J., & Chen, Z. (2008). Extended Bayesian information criteria for model selection with large model spaces. Biometrika, 95(3), 759-771.
This function can be used to select a model using any fit index
lassoSelect(object, select, minimize = TRUE, refit = TRUE, lassoTol = 1e-04)
lassoSelect(object, select, minimize = TRUE, refit = TRUE, lassoTol = 1e-04)
object |
An |
select |
A raw R expression using names used in the |
minimize |
Logical. Minimize or maximize? |
refit |
Logical. Should the new best model be refitted. |
lassoTol |
Tolerance for absolute values to be treated as zero in counting parameters. |
Sacha Epskamp <[email protected]>
## Not run: # Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Search best fitting omega_theta: res <- lvnetLasso(Data, "omega_theta", lambda = Lambda) res$best summary(res) # Update to use EBIC: resEBIC <- lassoSelect(res, ebic) summary(resEBIC) # Update to use minimal fitting model with RMSEA < 0.05: resMinimal <- lassoSelect(res, df * (rmsea < 0.05), minimize = FALSE) summary(resMinimal) ## End(Not run)
## Not run: # Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Search best fitting omega_theta: res <- lvnetLasso(Data, "omega_theta", lambda = Lambda) res$best summary(res) # Update to use EBIC: resEBIC <- lassoSelect(res, ebic) summary(resEBIC) # Update to use minimal fitting model with RMSEA < 0.05: resMinimal <- lassoSelect(res, df * (rmsea < 0.05), minimize = FALSE) summary(resMinimal) ## End(Not run)
This function can be used to easily generate input matrices for lvnet based on a lavaan model.
lav2lvnet(model, data, std.lv = TRUE, lavaanifyOps = list(auto = TRUE, std.lv = std.lv))
lav2lvnet(model, data, std.lv = TRUE, lavaanifyOps = list(auto = TRUE, std.lv = std.lv))
model |
Lavaan model syntax |
data |
The dataset. Only used to extract order of variables names from the columnnames. |
std.lv |
Should the model be identified by constraining latent variable variance to 1. Defaults to |
lavaanifyOps |
A list with other options sent to |
A list with the model matrices for lambda
, psi
, theta
and beta
Sacha Epskamp <[email protected]>
## Not run: library("lavaan") # Load dataset: data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # lavaan model HS.model <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 ' # fit via lavaan: lavFit <- cfa(HS.model, HolzingerSwineford1939[7:15],std.lv=TRUE) # Fit via lvnet: mod <- lav2lvnet(HS.model, HolzingerSwineford1939[7:15]) lvnetFit <- lvnet(Data, lambda = mod$lambda, psi = mod$psi) # Compare: Compare <- data.frame( lvnet = round(unlist(lvnetFit$fitMeasures)[c("npar","df","chisq","fmin","aic","bic", "rmsea","cfi","tli","nfi","logl")],3), lavaan = round(fitMeasures(lavFit)[c("npar","df","chisq","fmin","aic","bic","rmsea", "cfi","tli","nfi","logl")],3)) Compare ## End(Not run)
## Not run: library("lavaan") # Load dataset: data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # lavaan model HS.model <- ' visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 ' # fit via lavaan: lavFit <- cfa(HS.model, HolzingerSwineford1939[7:15],std.lv=TRUE) # Fit via lvnet: mod <- lav2lvnet(HS.model, HolzingerSwineford1939[7:15]) lvnetFit <- lvnet(Data, lambda = mod$lambda, psi = mod$psi) # Compare: Compare <- data.frame( lvnet = round(unlist(lvnetFit$fitMeasures)[c("npar","df","chisq","fmin","aic","bic", "rmsea","cfi","tli","nfi","logl")],3), lavaan = round(fitMeasures(lavFit)[c("npar","df","chisq","fmin","aic","bic","rmsea", "cfi","tli","nfi","logl")],3)) Compare ## End(Not run)
The lvglasso algorithm to estimate network structures containing latent variables, as proposed by Yuan (2012). Uses the glasso package (Friedman, Hastie and Tibshirani, 2014) and mimics input and output of the glasso
function.
lvglasso(S, nLatents, rho = 0, thr = 1e-04, maxit = 10000, lambda)
lvglasso(S, nLatents, rho = 0, thr = 1e-04, maxit = 10000, lambda)
S |
Sample variance-covariance matrix |
nLatents |
Number of latent variables. |
rho |
The LASSO tuning parameter |
thr |
The threshold to use for convergence |
maxit |
Maximum number of iterations |
lambda |
The lambda argument containing factor loadings, only used for starting values! |
A list of class lvglasso
containing the following elements:
w |
The estimated variance-covariance matrix of both observed and latent variables |
wi |
The estimated inverse variance-covariance matrix of both observed and latent variables |
pcor |
Estimated partial correlation matrix of both observed and latent variables |
observed |
Logical vector indicating which elements of w, wi and pcor are observed |
niter |
The number of iterations used |
lambda |
The estimated lambda matrix, when result is transformed to EFA model |
theta |
The estimated theta matrix |
omega_theta |
The estimated omega_theta matrix |
psi |
The estimated psi matrix |
Sacha Epskamp <[email protected]>
Yuan, M. (2012). Discussion: Latent variable graphical model selection via convex optimization.The Annals of Statistics,40, 1968-1972.
Jerome Friedman, Trevor Hastie and Rob Tibshirani (2014). glasso: Graphical lasso-estimation of Gaussian graphical models. R package version 1.8. http://CRAN.R-project.org/package=glasso
This function utilizes OpenMx (Boker et al., 2011, 2014) to confirmatory test latent variable network models between P manifests and M latents. See the details section for information about the modeling framework used. All the input matrices can be assigned R matrices with numbers indicating fixed values and NA indicating a value is free to estimate.
lvnet(data, lambda, beta, omega_theta, delta_theta, omega_psi, delta_psi, psi, theta, sampleSize, fitInd, fitSat, startValues = list(), scale = FALSE, nLatents, lasso = 0, lassoMatrix, lassoTol = 1e-4, ebicTuning = 0.5, mimic = c("lavaan","lvnet"), fitFunction = c("penalizedML", "ML"), exogenous)
lvnet(data, lambda, beta, omega_theta, delta_theta, omega_psi, delta_psi, psi, theta, sampleSize, fitInd, fitSat, startValues = list(), scale = FALSE, nLatents, lasso = 0, lassoMatrix, lassoTol = 1e-4, ebicTuning = 0.5, mimic = c("lavaan","lvnet"), fitFunction = c("penalizedML", "ML"), exogenous)
data |
An N (sample size) x P matrix or data frame containing the raw data, or a P x P variance-covariance matrix. |
lambda |
A P x M matrix indicating factor loadings. Defaults to a full NA P x M matrix if psi or omega_psi is not missing, or a P x 0 dummy matrix. |
beta |
An M x M matrix indicating linear effects between latent variables. Defaults to an M x M matrix containing only zeroes. |
omega_theta |
A P x P matrix encoding the residual network structure. By default, theta is modeled instead. |
delta_theta |
A P x P diagonal scaling matrix. Defaults to NA on all diagonal elements. Only used if omega_theta is modeled. |
omega_psi |
An M x M matrix containing the latent network structure. Dy default, psi is modeled instead. |
delta_psi |
A diagonal M x M scaling matrix. Defaults to an identity matrix. Only used if omega_psi is modeled. |
psi |
An M x M variance-covariance matrix between latents and latent residuals. Defaults to a full NA matrix. |
theta |
A P x P variance-covariance matrix of residuals of the observed variables. Defaults to a diagonal matrix containing NAs |
sampleSize |
The sample size, only used if |
fitInd |
The fit of the independence model. Used to speed up estimation fitting multiple models. |
fitSat |
The fit of the saturated model. Used to speed up estimation fitting multiple models. |
startValues |
An optional named list containing starting values of each model. e.g., |
scale |
Logical, should data be standardized before running lvnet? |
nLatents |
The number of latents. Allows for quick specification when |
lasso |
The LASSO tuning parameter. |
lassoMatrix |
Character vector indicating the names of matrices to apply LASSO regularization on. e.g., |
lassoTol |
Tolerance for absolute values to be treated as zero in counting parameters. |
ebicTuning |
Tuning parameter used in extended Bayesian Information Criterion. |
mimic |
If set to |
fitFunction |
The fit function to be used. |
exogenous |
Numeric vector indicating which variables are exogenous. |
The modeling framework follows the all-y LISREL framework for Structural Equation Models (SEM; Hayduk, 1987) to model relationships between P observed variables and M latent variables:
sigma = lambda * (I - beta)^(-1) psi (I - beta)^(-1 T) * lambda^T + theta
Where Sigma is the P x P model-implied covariance matrix, lambda a P x M matrix of factor loadings, B an M x M matrix containing regression effects between latent variables, Psi a M x M covariance matrix of the latent variables/residuals and Theta a P x P covariance matrix of residuals of the observed indicators.
The lvnet function allows for two extensions of this modeling framework. First, psi can be chosen to be modeled as follows:
psi = delta_psi (I - omega_psi)^(-1) delta_psi
In which delta_psi is a M x M diagonal scaling matrix and omega_psi a M x M matrix containing zeroes on the diagonal and partial correlation coefficients on the offdiagonal values of two latent variables conditioned on all other latent variables. omega_psi therefore corresponds to a Gaussian Graphical Model, or a network structure.
Similarly, theta can be chosen to be modeled as follows:
theta = delta_theta (I - omega_theta)^(-1) delta_theta
In which delta_theta is a P x P diagonal scaling matrix and omega_theta a P x P matrix containing zeroes on the diagonal and partial correlation coefficients on the offdiagonal values of two residuals conditioned on all other residuals.
Modeling omega_psi is termed Latent Network Modeling (LNM) and modeling omega_theta is termed Residual Network Modeling (RNM). lvnet automatically chooses the appropriate modeling framework based on the input.
An lvnet
object, which is a list containing the following elements:
matrices |
A list containing thee estimated model matrices |
sampleStats |
A list containing the covariance matrix ( |
mxResults |
The OpenMx object of the fitted model |
fitMeasures |
A named list containing the fit measures of the fitted model |
Sacha Epskamp <[email protected]>
Boker, S. M., Neale, M., Maes, H., Wilde, M., Spiegel, M., Brick, T., ... Fox, J. (2011). OpenMx: an open source extended structural equation modelingframework. Psychometrika, 76(2), 306-317
Boker, S. M., Neale, M. C., Maes, H. H., Wilde, M. J., Spiegel, M., Brick, T. R., ..., Team OpenMx. (2014). Openmx 2.0 user guide [Computer software manual].
Hayduk, L. A. (1987).Structural equation modeling with LISREL: Essentials advances. Baltimore, MD, USA: Johns Hopkins University Press.
# Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Fit CFA model: CFA <- lvnet(Data, lambda = Lambda) # Latent network: Omega_psi <- matrix(c( 0,NA,NA, NA,0,0, NA,0,0 ),3,3,byrow=TRUE) # Fit model: LNM <- lvnet(Data, lambda = Lambda, omega_psi=Omega_psi) # Compare fit: lvnetCompare(cfa=CFA,lnm=LNM) # Summary: summary(LNM) # Plot latents: plot(LNM, "factorStructure")
# Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Fit CFA model: CFA <- lvnet(Data, lambda = Lambda) # Latent network: Omega_psi <- matrix(c( 0,NA,NA, NA,0,0, NA,0,0 ),3,3,byrow=TRUE) # Fit model: LNM <- lvnet(Data, lambda = Lambda, omega_psi=Omega_psi) # Compare fit: lvnetCompare(cfa=CFA,lnm=LNM) # Summary: summary(LNM) # Plot latents: plot(LNM, "factorStructure")
Compares several results of lvnet
lvnetCompare(...) ## S3 method for class 'lvnet' anova(object, ...)
lvnetCompare(...) ## S3 method for class 'lvnet' anova(object, ...)
object |
An |
... |
Any number of |
Sacha Epskamp <[email protected]>
This function runs lvnet
for a number of different tuning parameters, selects the best model based on some criterion and refits that model to obtain accurate parameter estimates. The lassoSelect
function can afterwards be used to select a different model.
lvnetLasso(data, lassoMatrix, lassoTol = 1e-04, nTuning = 20, tuning.min = 0.01, tuning.max = 0.5, criterion = c("bic", "aic", "ebic"), verbose = TRUE, refitFinal = TRUE, refitAll = FALSE, nCores = 1, ...)
lvnetLasso(data, lassoMatrix, lassoTol = 1e-04, nTuning = 20, tuning.min = 0.01, tuning.max = 0.5, criterion = c("bic", "aic", "ebic"), verbose = TRUE, refitFinal = TRUE, refitAll = FALSE, nCores = 1, ...)
data |
The data argument as used in |
lassoMatrix |
Vector indicating the matrix or matrices to use in LASSO optmimization |
lassoTol |
Tolerance for absolute values to be treated as zero in counting parameters. |
nTuning |
Number of tuning parameters to estimate. |
tuning.min |
Minimal tuning parameter |
tuning.max |
Maximal tuning parameter |
criterion |
Criterion to use in model selection |
verbose |
Should progress be printed to the console? |
refitFinal |
Logical, should the best fitting model be refitted without LASSO regularization? |
refitAll |
Logical, should *all* models be refitted without LASSO regularization (but with zeroes constrained) before evaluating fit criterium? |
nCores |
Number of cores to use in parallel computing. |
... |
Arguments sent to |
Sacha Epskamp <[email protected]>
# Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Search best fitting omega_theta: ## Not run: res <- lvnetLasso(Data, "omega_theta", lambda = Lambda) res$best summary(res) ## End(Not run)
# Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Search best fitting omega_theta: ## Not run: res <- lvnetLasso(Data, "omega_theta", lambda = Lambda) res$best summary(res) ## End(Not run)
Obtain fit indices from the estimated model parameters on a new dataset.
lvnetRefit(lvnetObject, data, sampleSize)
lvnetRefit(lvnetObject, data, sampleSize)
lvnetObject |
Output of |
data |
New dataset or variance-covariance matrix. |
sampleSize |
Sample size (if |
Sacha Epskamp <[email protected]>
Performs stepwise search to optimize the structure of omega_theta, omega_psi, theta or psi. Starts at empty or full structure and iteratively adds or removes edges to optimize the criterion.
lvnetSearch(data, matrix = c("omega_theta", "omega_psi", "theta", "psi"), criterion = c("bic", "ebic","chisq","aic"), start = c("default","empty","full"), alpha = 0.05, lambda, sampleSize, maxIter, nCores = 1, maxChange = 1, ..., verbose = TRUE, file, startValues = list())
lvnetSearch(data, matrix = c("omega_theta", "omega_psi", "theta", "psi"), criterion = c("bic", "ebic","chisq","aic"), start = c("default","empty","full"), alpha = 0.05, lambda, sampleSize, maxIter, nCores = 1, maxChange = 1, ..., verbose = TRUE, file, startValues = list())
data |
The data argument as used in |
matrix |
Character string indicating the matrix to be optimized. Can be |
criterion |
Character string indicating the criterion to be used. |
start |
A character string indicating the structure of the matrix at the start of the algorithm. |
alpha |
The alpha level for chi-square significance testing. |
lambda |
The lambda argument as used in |
sampleSize |
The sample size, only used if |
maxIter |
The maximum number of edges to test. Defaults to M(M-1)/2 |
nCores |
Number of cores to use in parallel estimation. |
maxChange |
Set to higher than one to change multiple edges in each run. Each iteration, maxChange is reset to max(number of changed edges - 1, 1). Can result in instable results when searching |
... |
Arguments sent to |
verbose |
Logical if progress should be printed to the consile. |
file |
An optional character string containing a file name to store temporary results in. |
startValues |
A list containing start values as used in |
An object of class lvnetSearch
, which is a list containing:
best |
The |
modList |
A list containing the chain of fitted models |
niter |
The number of iterations used |
Sacha Epskamp <[email protected]>
# Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Search best fitting omega_psi: ## Not run: res <- lvnetSearch(Data, "omega_psi", lambda = Lambda) res$best ## End(Not run)
# Load dataset: library("lavaan") data(HolzingerSwineford1939) Data <- HolzingerSwineford1939[,7:15] # Measurement model: Lambda <- matrix(0, 9, 3) Lambda[1:3,1] <- NA Lambda[4:6,2] <- NA Lambda[7:9,3] <- NA # Search best fitting omega_psi: ## Not run: res <- lvnetSearch(Data, "omega_psi", lambda = Lambda) res$best ## End(Not run)
Plot method for lvnet
. For lvnetSearch
and lvnetLasso
objects this is simply defined as plot(object$best, ...)
## S3 method for class 'lvnet' plot(x, what = c("factorStructure", "residual", "latent"), partial, layout = "circle", ...) ## S3 method for class 'lvnetLasso' plot(x, ...) ## S3 method for class 'lvnetSearch' plot(x, ...)
## S3 method for class 'lvnet' plot(x, what = c("factorStructure", "residual", "latent"), partial, layout = "circle", ...) ## S3 method for class 'lvnetLasso' plot(x, ...) ## S3 method for class 'lvnetSearch' plot(x, ...)
x |
An |
what |
What to plot? |
partial |
Plot partial correlations instead of correlations? Defaults to |
layout |
The layour argument as used in |
... |
Arguments sent to |
Sacha Epskamp <[email protected]>
Plot method for lvnet
. For lvnetSearch
and lvnetLasso
objects this is simply defined as summary(object$best, ...)
## S3 method for class 'lvnet' summary(object, include = c("input", "chisq", "infcrit", "fitindices", "rmsea", "parests"), digits = 3, ...) ## S3 method for class 'lvnetLasso' summary(object, ...) ## S3 method for class 'lvnetSearch' summary(object, ...)
## S3 method for class 'lvnet' summary(object, include = c("input", "chisq", "infcrit", "fitindices", "rmsea", "parests"), digits = 3, ...) ## S3 method for class 'lvnetLasso' summary(object, ...) ## S3 method for class 'lvnetSearch' summary(object, ...)
object |
An |
include |
Vector indicating what to include? |
digits |
Number of digits to round to. |
... |
Not used. |
Sacha Epskamp <[email protected]>