---
title: "Package 'SEMsens'"
author: "Walter Leite (University of Florida) & Zuchao Shen (University of Florida)"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette

vignette: >
  %\VignetteIndexEntry{Package 'SEMsens'}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---
An analysis based on structural equation modeling may suffer from the impact of a potential missing confounder that may change its conclusions (Harring, McNeish, & Hancock, 2017). This package is a tool to evaluate the sensitivity of structural equation models to potential missing confounders using the Ant Colony Optimization (ACO; Colorni, Dorigo, & Maniezzo, 1992; Dorigo & Stützle, 2004; Socha & Dorigo, 2008) algorithm. The reference for the current package is: Leite, W., Shen, Z., Marcoulides, K., Fish, C., & Harring, J. (2022). Using ant colony optimization for sensitivity analysis in structural equation modeling. Structural Equation Modeling: A Multidisciplinary Journal, 29 (1), 47-56.


The current version includes three main functions and they are

- *gen.sens.pars* function: This function generates a set of required sensitivity parameters according to the rank of object function, with which the method has been developed by Socha & Dorigo (2008). 


- *sa.aco* function: This function  automatically performs the search for an omitted confounder in structural equation modeling using the ACO algorithm


- *sens.table* function: This function provides five summary tables of results produced in the *sa.aco* function.

Next, we use an example to illustrate how to perform sensitivity analysis in structural equation modeling.

## 1. Function *sa.aco* 

Given a data set (or variance covariance matrix) and an analytic model, this function searches an omitted confounder to optimize the objective function. *sa.aco* function calls *gen.sens.pars* function to perform the algorithm together. 

We need the following information/arguments to perform the search

- data: The data set used for an analysis. If there is no data available, use covariance matrix instead.
- sample.cov: Covariance matrix.
- sample.nobs: Number of observations for covariance matrix.
- model: The analytic model of interest.
- sens.model: Sensitivity analysis model template for structural equation modeling with a phantom variable. This is the model of interest with a phantom variable and sensitivity parameters added. See the example provided.
- opt.fun: Customized or preset object function for optimization.
- ......

To see more arguments, please run ?sa.aco in R or RStudio.

### An exmaple

The example is from: Kim, Y. S. G., & Schatschneider, C. (2017). Expanding the developmental models of writing: A direct and indirect effects model of developmental writing (DIEW). Journal of Educational psychology, 109(1), 35-50.


```{r, message=FALSE, warning=FALSE}
# Load lavaan and SEMsens packages
require(lavaan)
require(SEMsens)
set.seed(1)
```

```{r}
# STEP 1: Prepare data:
# Lower diagonal correlation matrix in the study by Kim & Schatschneider (2017)
lower = '
1.00
.40 1.00
.40 .64 1.00
.41 .66 .61 1.00
.42 .52 .53 .61 1.00
.34 .50 .46 .53 .48 1.00
.42 .47 .41 .43 .47 .55 1.00
.39 .46 .39 .30 .21 .30 .37 1.00
.24 .31 .30 .31 .26 .32 .27 .56 1.00
.33 .35 .35 .40 .31 .25 .35 .51 .42 1.00
.30 .42 .36 .32 .24 .37 .43 .44 .37 .49 1.00'

# Convert to full covariance matrix
sample.cov = getCov(lower, sds = c(5.64,14.68,6.57,6.07,3.39,10.16,6.11,4.91,15.59,0.96,0.99),
              names = c("Working_memory",
                        "Vocabulary",
                        "Grammar",
                        "Inference",
                        "ToM",
                        "TNL",
                        "Expository",
                        "Spelling",
                        "Sentence_copying",
                        "One_day",
                        "Castle"))
 
# STEP 2: Set up analytic model and sensitivity anaysis model
  # The original analytic model
model <-'Vocabulary~Working_memory
  Grammar~Working_memory
  Inference~Vocabulary+Grammar+Working_memory
  ToM~Vocabulary+Grammar+Working_memory
  Spelling~Working_memory
  Sentence_copying~Working_memory
  Discourse~Inference+ToM+Vocabulary+Grammar+Working_memory
  Writing~Spelling+Sentence_copying+Discourse

  Discourse=~TNL+Expository
  Writing=~One_day+Castle

  Vocabulary~~Grammar
  Grammar~~Sentence_copying
  Vocabulary~~Sentence_copying
  Grammar~~Spelling
  Vocabulary~~Spelling
  Inference~~ToM
  Discourse~~Sentence_copying
  Discourse~~Spelling
  Spelling~~Sentence_copying'

  # A sensitivity analysis model template, which additionally includes paths
  #  from a phantom variable to a set of variables (= number of sensitivity parameters)
  #   in the analytic model.
sens.model <- 'Vocabulary~Working_memory
  Grammar~Working_memory
  Inference~Vocabulary+Grammar+Working_memory
  ToM~Vocabulary+Grammar+Working_memory
  Spelling~Working_memory
  Sentence_copying~Working_memory
  Discourse~Inference+ToM+Vocabulary+Grammar+Working_memory
  Writing~Spelling+Sentence_copying+Discourse

  Discourse=~TNL+Expository
  Writing=~One_day+Castle

  Vocabulary~~Grammar
  Grammar~~Sentence_copying
  Vocabulary~~Sentence_copying
  Grammar~~Spelling
  Vocabulary~~Spelling
  Inference~~ToM
  Discourse~~Sentence_copying
  Discourse~~Spelling
  Spelling~~Sentence_copying

  Working_memory ~ phantom1*phantom
  Grammar ~ phantom2*phantom
  Vocabulary ~ phantom3*phantom
  ToM ~ phantom4*phantom
  Inference ~ phantom5*phantom
  Spelling ~ phantom6*phantom
  Sentence_copying  ~ phantom7*phantom
  Discourse ~ phantom8*phantom
  Writing ~ phantom9*phantom
  phantom =~ 0 # added for mean of zero
  phantom ~~ 1*phantom'

# STEP 3: Set up the paths of interest to be evaluated in sensitivity analysis.
  paths <- 'Vocabulary~Working_memory
  Grammar~Working_memory
  Inference~Vocabulary+Grammar+Working_memory
  ToM~Vocabulary+Grammar+Working_memory
  Spelling~Working_memory
  Sentence_copying~Working_memory
  Discourse~Inference+ToM+Vocabulary+Grammar+Working_memory
  Writing~Spelling+Sentence_copying+Discourse'

  # STEP 4: Perform sensitivity analysis.
my.sa <-sa.aco(model = model, sens.model = sens.model, sample.cov = sample.cov,
               sample.nobs = 193, k = 50, max.value= 2000, max.iter = 100,
               opt.fun = 4, ## from significant to just significant
               paths = paths, seed = 1, verbose = FALSE)
# We set up a max iteration of 100 and solution archive length of 50 for 
# illustration purpose. Please specify a larger number of iteration (e.g., 1000),
#  and a larger k (e.g., 100).

```

## 2. Function *sens.tables* 
*sens.tables* function can help summarize the sensitivity analysis results. Beyond this function, investigators always can summarize the results by accessing to the results in *sa.aco* function.

```{r}
my.table <- sens.tables(my.sa)
# Table 1: Summary of the sensitivity analysis for each path
my.table[[1]]

# Table 2:  Summary of the sensitivity parameters
my.table[[2]]

# Table 3: The sensitivity parameters lead to the minimum coefficient for each
my.table[[3]]

# Table 4: The sensitivity parameters lead to the maximum coefficient for each path
my.table[[4]]

# Table 5: The sensitivity parameters lead to change in significance for each path
my.table[[5]]

```