Introduction to ISMtools

Yi Tang

2026-03-09

Overview

ISMtools is a comprehensive R package for Interpretive Structural Modelling (ISM) analysis. ISM is a well-established methodology for identifying and summarizing relationships among specific elements which define an issue or problem (Warfield, 1974).

This vignette provides a step-by-step guide to using ISMtools for ISM analysis.

Installation

# Install from CRAN (once available)
install.packages("ISMtools")

# Or install development version from GitHub
# devtools::install_github("tangyi/ISMtools")

Loading the Package

library(ISMtools)

ISM Analysis Workflow

A typical ISM analysis follows these steps:

  1. Define elements: Identify the factors/variables to be analyzed
  2. Create adjacency matrix: Establish pairwise relationships
  3. Compute reachability matrix: Calculate transitive closure
  4. Level partitioning: Determine hierarchical structure
  5. Visualization: Create ISM diagrams

Step 1: Creating an Adjacency Matrix

Method 1: Direct Matrix Creation

# Create a 5x5 adjacency matrix directly
# 1 indicates element i influences element j
adj_matrix <- matrix(c(
  0, 1, 0, 0, 0,
  0, 0, 1, 0, 0,
  0, 0, 0, 1, 1,
  0, 0, 0, 0, 0,
  0, 0, 0, 0, 0
), nrow = 5, byrow = TRUE)

# Add row and column names
rownames(adj_matrix) <- colnames(adj_matrix) <- paste0("F", 1:5)
print(adj_matrix)
#>    F1 F2 F3 F4 F5
#> F1  0  1  0  0  0
#> F2  0  0  1  0  0
#> F3  0  0  0  1  1
#> F4  0  0  0  0  0
#> F5  0  0  0  0  0

Method 2: Using create_relation_matrix()

# Create an empty matrix of specified size
empty_matrix <- create_relation_matrix(4)
print(empty_matrix)
#>   1 2 3 4
#> 1 0 0 0 0
#> 2 0 0 0 0
#> 3 0 0 0 0
#> 4 0 0 0 0

Method 3: Converting from Edge List

# From a data frame
edge_df <- data.frame(
  source = c("A", "A", "B", "C"),
  target = c("B", "C", "D", "D")
)

adj_from_df <- convert_to_matrix(edge_df, from = "source", to = "target")
print(adj_from_df)
#>   A B C D
#> A 0 1 1 0
#> B 0 0 0 1
#> C 0 0 0 1
#> D 0 0 0 0
# From a matrix edge list
edge_mat <- matrix(c(
  "X", "Y",
  "Y", "Z",
  "X", "Z"
), ncol = 2, byrow = TRUE)

adj_from_mat <- convert_to_matrix(edge_mat)
print(adj_from_mat)
#>   X Y Z
#> X 0 1 1
#> Y 0 0 1
#> Z 0 0 0

Step 2: Computing the Reachability Matrix

The reachability matrix shows all direct and indirect relationships between elements. ISMtools uses Warshall’s algorithm for efficient computation.

# Using our 5x5 adjacency matrix
reach_matrix <- compute_reachability(adj_matrix)
print(reach_matrix)
#>    F1 F2 F3 F4 F5
#> F1  1  1  1  1  1
#> F2  0  1  1  1  1
#> F3  0  0  1  1  1
#> F4  0  0  0  1  0
#> F5  0  0  0  0  1

In the reachability matrix: - reach_matrix[i,j] = 1 means element i can reach element j (directly or indirectly) - The diagonal represents self-reachability

Step 3: Level Partitioning

Level partitioning determines the hierarchical structure of elements based on their reachability and antecedent sets.

levels <- level_partitioning(reach_matrix)
print(levels)
#> ISM Hierarchical Levels
#> =======================
#> (Level 1 = Top/Outcomes, Higher levels = Drivers)
#> 
#> Level 1: F4, F5
#> Level 2: F3
#> Level 3: F2
#> Level 4: F1
#> 
#> Total: 4 levels, 5 elements

Elements at higher levels (e.g., Level 1) are outcomes/effects, while elements at lower levels are root causes/drivers.

Step 4: Visualization

Static ISM Diagram

plot_ism(reach_matrix)

Interactive ISM Diagram

The interactive visualization allows you to: - Drag nodes to reposition them - Zoom in/out - Highlight connected nodes on hover - Filter by level

# Interactive visualization (requires browser)
plot_interactive_ism(reach_matrix, 
                     node_labels = paste0("Factor ", 1:5),
                     level_result = levels)

Complete Example: Project Risk Analysis

Let’s walk through a complete example analyzing project risk factors.

# Define risk factors
factors <- c(
  "Budget Constraints",      # F1

  "Resource Shortage",       # F2  
  "Technical Complexity",    # F3
  "Poor Communication",      # F4
  "Schedule Pressure",       # F5
  "Quality Issues",          # F6
  "Project Failure"          # F7
)

# Create adjacency matrix based on expert judgment
# F1 -> F2, F5
# F2 -> F3, F6
# F3 -> F6
# F4 -> F2, F3, F6
# F5 -> F4, F6
# F6 -> F7

risk_adj <- matrix(0, nrow = 7, ncol = 7)
rownames(risk_adj) <- colnames(risk_adj) <- paste0("F", 1:7)

# Define relationships
risk_adj["F1", c("F2", "F5")] <- 1
risk_adj["F2", c("F3", "F6")] <- 1
risk_adj["F3", "F6"] <- 1
risk_adj["F4", c("F2", "F3", "F6")] <- 1
risk_adj["F5", c("F4", "F6")] <- 1
risk_adj["F6", "F7"] <- 1

print("Adjacency Matrix:")
#> [1] "Adjacency Matrix:"
print(risk_adj)
#>    F1 F2 F3 F4 F5 F6 F7
#> F1  0  1  0  0  1  0  0
#> F2  0  0  1  0  0  1  0
#> F3  0  0  0  0  0  1  0
#> F4  0  1  1  0  0  1  0
#> F5  0  0  0  1  0  1  0
#> F6  0  0  0  0  0  0  1
#> F7  0  0  0  0  0  0  0
# Compute reachability
risk_reach <- compute_reachability(risk_adj)
print("Reachability Matrix:")
#> [1] "Reachability Matrix:"
print(risk_reach)
#>    F1 F2 F3 F4 F5 F6 F7
#> F1  1  1  1  1  1  1  1
#> F2  0  1  1  0  0  1  1
#> F3  0  0  1  0  0  1  1
#> F4  0  1  1  1  0  1  1
#> F5  0  1  1  1  1  1  1
#> F6  0  0  0  0  0  1  1
#> F7  0  0  0  0  0  0  1
# Level partitioning
risk_levels <- level_partitioning(risk_reach)
print("Hierarchical Levels:")
#> [1] "Hierarchical Levels:"
print(risk_levels)
#> ISM Hierarchical Levels
#> =======================
#> (Level 1 = Top/Outcomes, Higher levels = Drivers)
#> 
#> Level 1: F7
#> Level 2: F6
#> Level 3: F3
#> Level 4: F2
#> Level 5: F4
#> Level 6: F5
#> Level 7: F1
#> 
#> Total: 7 levels, 7 elements
# Visualize
plot_ism(risk_reach)

Interpretation

From this analysis: - Level 1 (Top): F7 (Project Failure) - the ultimate outcome - Level 2: F6 (Quality Issues) - direct cause of failure - Level 3: F3 (Technical Complexity) - intermediate factor - Level 4: F2 (Resource Shortage), F4 (Poor Communication) - Level 5: F5 (Schedule Pressure) - Level 6 (Bottom): F1 (Budget Constraints) - root cause

This hierarchical structure suggests that addressing budget constraints (F1) could have cascading positive effects throughout the project.

References

Warfield, J. N. (1974). Developing interconnection matrices in structural modeling. IEEE Transactions on Systems, Man, and Cybernetics, SMC-4(1), 81-87.

Session Info

sessionInfo()
#> R version 4.4.2 (2024-10-31 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26100)
#> 
#> Matrix products: default
#> 
#> 
#> locale:
#> [1] LC_COLLATE=C                               
#> [2] LC_CTYPE=Chinese (Simplified)_China.utf8   
#> [3] LC_MONETARY=Chinese (Simplified)_China.utf8
#> [4] LC_NUMERIC=C                               
#> [5] LC_TIME=Chinese (Simplified)_China.utf8    
#> 
#> time zone: Asia/Shanghai
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] ISMtools_0.1.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] digest_0.6.37     R6_2.5.1          fastmap_1.2.0     xfun_0.49        
#>  [5] cachem_1.1.0      knitr_1.49        htmltools_0.5.8.1 rmarkdown_2.29   
#>  [9] lifecycle_1.0.4   cli_3.6.3         sass_0.4.9        jquerylib_0.1.4  
#> [13] compiler_4.4.2    rstudioapi_0.17.1 tools_4.4.2       evaluate_1.0.1   
#> [17] bslib_0.8.0       yaml_2.3.10       rlang_1.1.4       jsonlite_1.8.9