knitr::opts_chunk$set(echo = TRUE, message = FALSE)
#change this later to just call the library and function source("./R/lavaan_models.R") #call the data - this will be in the statstools - data folder eventually library(RCurl) master <- read.csv(text = getURL("https://raw.githubusercontent.com/doomlab/MeMoBootR/master/examples/mediation1.csv")) #oh this is mt cars, I should do a better example names(master) #try the function output.model <- lavaan.model(y = "mpg", x = "cyl", m = "hp", data = master, B = 100, print = FALSE) #just to save time now #to get the data input.data <- lavInspect(output.model[["fit"]], what = "data") head(input.data)
# Variables to lavaan model ----------------------------------------------- require(lavaan) lavaan.model2 <- function(y, x, # Mediators m, # Categorical variables categorical = NULL, # Covariates cv = NULL, # Covariates for Y ~ X (and Y ~ M) cv.yx = FALSE, # Covariates for M ~ X cv.mx = FALSE, data, # Test statistic # Robust variants: # "Satorra-Bentler" and "Yuan-Bentler" test = "standard", # Number of bootstrap resamples B = 5000, seed = 1234, ci = .95, process.model = 4, print = TRUE) { # Set Seed set.seed(seed) # PROCESS Model 4 (Single Mediator) if (process.model == 4) { # Calculate SD of Y for partially standardized effect size sd.y <- sd(data[, y], na.rm = TRUE) # Direct effect # Y ~ X direct.eff <- ifelse( # Covariates for Y ~ X and Y ~ M automatically: !is.null(cv) & isTRUE(cv.yx), # Y ~ c*X + b*M + CV1 + ... CVn paste0(y, "~", "c*", x, "+", paste0(cv, collapse = "+")), # Y ~ c*X paste0(y, "~", "c*", x) ) # Mediator(s) # Check length of m if (length(m) == 1) { # Mediator # M ~ X mediator.mx <- ifelse( # Covariates for M ~ X !is.null(cv) & isTRUE(cv.mx), # M ~ a*X + CV1 + ... CVn paste0(m, "~", "a*", x, "+", paste0(cv, collapse = "+")), # M ~ a*X paste0(m, "~", "a*", x) ) # Y ~ M mediator.ym <- paste0(y, "~", "b*", m) # Indirect effect indirect.eff <- "ab := a*b" # Total effect total.eff <- "total_effect := c + (a*b)" # Partially standardized indirect effect size a.es <- paste0("ab_es := ab/", sd.y) # Specify model model <- paste( direct.eff, mediator.mx, mediator.ym, indirect.eff, total.eff, a.es, sep = "\n" ) } else { # Declare variables for loop mediator.mx <- vector("character", length = length(m)) indirect.eff <- vector("character", length = length(m)) mediator.ym <- vector("character", length = length(m)) total.eff <- vector("character", length = length(m)) indirect.es <- vector("character", length = length(m)) # Loop through mediators for (i in 1:length(m)) { # Covariates have been selected for M ~ X if (!is.null(cv) & isTRUE(cv.mx)) { mediator.mx[i] <- paste0( m[i], "~", "a", i, "*", x, "+", paste0(cv, collapse = "+") ) } else { mediator.mx[i] <- paste0( m[i], "~", "a", i, "*", x ) } # Y ~ M mediator.ym[i] <- paste0(y, "~", "b", i, "*", m[i]) # Indirect effect indirect.eff[i] <- paste0("a", i, "b", i, ":=", "a", i, "*", "b", i) # Total effect total.eff[i] <- paste0("(", "a", i, "*", "b", i, ")") # Partially standardized indirect effect size indirect.es[i] <- paste0( paste0("a", i, "b", i, "_es:=", "(a", i, "*", "b", i, ")/", sd.y) ) } # Collapse variables mediator.mx <- paste0(mediator.mx, collapse = "\n") mediator.ym <- paste0(mediator.ym, collapse = "\n") indirect.eff <- paste0(indirect.eff, collapse = "\n") indirect.es <- paste0(indirect.es, collapse = "\n") # Total indirect effect total.ind.eff <- paste0( "total_indirect:=", paste0(total.eff, collapse = "+") ) # Partially standardized total indirect effect total.ind.eff.es <- paste0( "total_indirect_es:=", "total_indirect/", sd.y ) # Total direct effect total.eff <- paste0("total_effect:=c+", paste0(total.eff, collapse = "+")) # Specify model model <- paste( direct.eff, mediator.mx, mediator.ym, indirect.eff, total.ind.eff, total.eff, indirect.es, total.ind.eff.es, sep = "\n" ) } # Run mediation analyses # Categorical variables if (!is.null(categorical)) { fit <- sem( model, ordered = categorical, data = data, # Requires DWLS for bootstrapping estimator = "DWLS", se = "robust.sem", bootstrap = B, missing = "ML" ###THIS SPOT#### ) } else { fit <- sem( model, data = data, se = "robust.sem", test = test, bootstrap = B ) } # Run bootstrap on coefficients est_boot <- bootstrapLavaan( fit, FUN = function(x) parameterestimates(x)$est, parallel = "multicore", R = B ) boot_out <- data.frame( param = as.character(parameterestimates(fit)$lab), t( rbind( est = parameterestimates(fit)$est, se.boot = apply(est_boot, 2, sd), apply(est_boot, 2, quantile, c((1 - ci) / 2, ci + (1 - ci) / 2)), p.boot = 2 * pmin(colMeans(est_boot > 0), colMeans(est_boot < 0)) ) ) ) # Remove empty parameters boot_out <- boot_out[boot_out$param != "", ] # Set column names colnames(boot_out)[c(4:5)] <- c("ci.lb.boot", "ci.ub.boot", "p.value") # Set row names rownames(boot_out) <- boot_out$param # Drop param variable boot_out <- boot_out[, -1] # Return fit and bootstrap results # Show summary results if (print) { cat( "\n", "\n", "Summary Results", "\n", "\n", sep = "" ) print( parameterEstimates( fit, zstat = TRUE, standardized = FALSE, cov.std = FALSE, rsquare = TRUE, output = "pretty" ) ) cat( "\n", "\n", "Bootstrap Results", "\n", "\n", sep = "" ) print(boot_out) } return( list( fit = fit, boot = boot_out ) ) } }
#messy data library(faux) temp <- messy(master, prop = .1, "hp", replace = NA) output.model2 <- lavaan.model(y = "mpg", x = "cyl", m = "hp", data = temp, B = 100, print = FALSE) #just to save time now summary(output.model2$fit) output.model2$boot input.data <- lavInspect(output.model2$fit, what = "data") View(input.data) ##look up runmi - semtools
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.