Structural Equation Modeling (SEM)
By- Rounak Choudhary
By- Rounak Choudhary
Structural Equation Modeling (SEM) is a powerful statistical technique that allows researchers to test complex cause-and-effect relationships among multiple variables, including both direct and indirect (mediated) effects. Unlike simple regression, SEM can model networks of relationships and account for both observed and latent (unmeasured) variables.
In ecology, SEM is widely used to understand how multiple environmental, biological, and spatial factors jointly influence ecosystem patterns and processes. It is especially valuable for hypothesis-driven modeling where variables are interdependent—for example, how land use affects vegetation structure, which in turn influences species richness. SEM helps disentangle direct vs. indirect effects, making it ideal for studying causal pathways in ecological systems, such as nutrient cycling, food webs, biodiversity responses, and landscape-scale interactions.
Pre Requirements:- You will need data in a CSV as follows:
# Install necessary packages (only once; comment out after installed)
install.packages("lavaan") # Core SEM modeling package
install.packages("semPlot") # For SEM diagram plotting
install.packages("lavaanPlot") # Simple wrapper for creating SEM diagrams with lavaan
install.packages("DiagrammeRsvg") # To convert graphs to SVG format
install.packages("rsvg") # For exporting SVG to PNG
# Load libraries
library(lavaan) # Core SEM modeling functions
library(semPlot) # Plotting SEM models
library(lavaanPlot) # Cleaner SEM plots
library(DiagrammeR) # Graph rendering (used internally by lavaanPlot)
library(DiagrammeRsvg) # Convert DiagrammeR object to SVG
library(rsvg) # Convert SVG to PNG
# Load your SEM-ready dataset (should be a data frame with one row per site/observation)
sem_data <- read.csv("C:/Users/Rounak Choudhary/Desktop/env.csv")
# Check column names in your dataset
names(sem_data)
# Fit a full multiple linear regression model using all candidate predictors for Taxa
full_model <- lm(Taxa ~ AIV + Tree + Bare + Crop + Grass + IJI + Area, data = sem_data)
# Perform stepwise model selection to identify the best subset of predictors
best_model <- step(full_model, direction = "both")
# View the summary of the best selected linear model
summary(best_model)
# Define SEM model structure using lavaan syntax as a character string
model <- '
Taxa ~ AIV + Tree + Bare + Area
'
# Fit the SEM model using lavaan
fit <- sem(model, data = sem_data)
# Show a detailed summary of the SEM model:
# - parameter estimates
# - fit statistics
# - standardized coefficients
summary(fit, fit.measures = TRUE, standardized = TRUE)
# Create a basic SEM plot from the model
lavaanPlot(
model = fit,
stand = TRUE, # Show standardized coefficients
coefs = TRUE, # Display numeric coefficients
covs = TRUE, # Show covariances (if present)
stars = "regress", # Add significance stars to regression paths
graph_options = list(rankdir = "LR") # Left-to-right layout
)
# Create an enhanced SEM plot with custom node and edge styles
lavaanPlot(
model = fit,
stand = TRUE,
coefs = TRUE,
covs = TRUE,
stars = "regress",
node_options = list( # Customize node appearance
shape = "rectangle",
color = "lightblue",
fontcolor = "black",
fontsize = 18,
style = "filled",
fixedsize = FALSE
),
edge_options = list( # Customize edge (arrow) appearance
color = "gray20",
fontcolor = "black",
fontsize = 16,
penwidth = 2
),
graph_options = list( # Customize graph layout and behavior
rankdir = "LR",
splines = "true",
layout = "dot"
)
)
# Store the SEM plot in a variable `p` as a DiagrammeR graph object
p <- lavaanPlot(
model = fit,
stand = TRUE,
coefs = TRUE,
covs = TRUE,
stars = "regress",
node_options = list(
shape = "rectangle",
color = "lightblue",
fontcolor = "black",
fontsize = 18,
style = "filled",
fixedsize = FALSE
),
edge_options = list(
color = "gray20",
fontcolor = "black",
fontsize = 16,
penwidth = 2
),
graph_options = list(
rankdir = "LR",
splines = "true",
layout = "dot"
)
)
# Convert the DiagrammeR graph to SVG format
svg_code <- DiagrammeRsvg::export_svg(p)
# Save the SVG as a high-resolution PNG image on your desktop
rsvg::rsvg_png(
charToRaw(svg_code),
"C:/Users/Rounak Choudhary/Desktop/sem_plot.png",
width = 1600,
height = 1000
)