TSQCA Reproducible Code (English)

This document provides reproducible code for TSQCA analyses.
It is designed to be inserted directly into a research article’s appendix
or provided as supplementary analysis documentation. All code is fully executable and ordered for reproducibility.


1. Load Packages

library(TSQCA)
library(QCA)
#> Warning: package 'QCA' was built under R version 4.4.3
#> Loading required package: admisc
#> Warning: package 'admisc' was built under R version 4.4.3
#> 
#> To cite package QCA in publications, please use:
#>   Dusa, Adrian (2019) QCA with R. A Comprehensive Resource.
#>   Springer International Publishing.
#> 
#> To run the graphical user interface, use: runGUI()

2. Load Data

# Adjust the file name as needed
library(TSQCA)
data("sample_data")
dat <- sample_data

# Outcome and conditions
outcome  <- "Y"
conditions <- c("X1", "X2", "X3")

# Quick inspection
str(dat)
#> 'data.frame':    80 obs. of  4 variables:
#>  $ Y : int  8 4 5 7 2 2 7 5 3 8 ...
#>  $ X1: int  7 2 6 8 8 9 8 8 1 5 ...
#>  $ X2: int  7 5 8 4 0 5 8 4 4 2 ...
#>  $ X3: int  1 6 6 5 3 4 5 3 6 8 ...
summary(dat)
#>        Y                X1               X2              X3        
#>  Min.   : 0.000   Min.   : 0.000   Min.   : 0.00   Min.   : 0.000  
#>  1st Qu.: 3.000   1st Qu.: 3.000   1st Qu.: 3.00   1st Qu.: 3.000  
#>  Median : 5.000   Median : 5.500   Median : 5.00   Median : 5.000  
#>  Mean   : 5.513   Mean   : 5.237   Mean   : 5.05   Mean   : 4.925  
#>  3rd Qu.: 7.250   3rd Qu.: 8.000   3rd Qu.: 7.25   3rd Qu.: 7.000  
#>  Max.   :10.000   Max.   :10.000   Max.   :10.00   Max.   :10.000

3. Baseline Thresholds

thrY_base <- 7
thrX_base <- 7

# Fixed X thresholds (for OTS–QCA)
thrX_vec <- c(
  X1 = thrX_base,
  X2 = thrX_base,
  X3 = thrX_base
)
thrX_vec
#> X1 X2 X3 
#>  7  7  7

4. CTS–QCA (ctSweepS)

Sweep a single condition X (example: X3).

sweep_var   <- "X3"   # Condition (X) whose threshold is swept
sweep_range <- 6:9    # Candidate threshold values to evaluate
thrY         <- 7     # Outcome (Y) threshold (fixed)
thrX_default <- 7     # Threshold for other X conditions (fixed)

res_cts <- ctSweepS(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_var      = "X3",
  sweep_range    = 6:9,
  thrY           = 7,
  thrX_default   = 7,
  dir.exp        = c(1, 1, 1),
  return_details = TRUE
)

summary(res_cts)
#> CTS-QCA Summary
#> =============== 
#> 
#> Analysis Parameters:
#>   Outcome: Y 
#>   Conditions: X1, X2, X3 
#>   Consistency cutoff: 0.8 
#>   Frequency cutoff: 1 
#> 
#> Results by Threshold:
#> 
#>  threshold expression inclS  covS n_solutions
#>          6      X1*X2 1.000 0.303           1
#>          7 X3 + X1*X2 0.906 0.879           1
#>          8 X3 + X1*X2 1.000 0.818           1
#>          9 X3 + X1*X2 1.000 0.515           1

Export:

write.csv(res_cts$summary, file = "TSQCA_CTS_results.csv", row.names = FALSE)

5. MCTS–QCA (ctSweepM)

Sweep multiple X thresholds simultaneously.

# Create a sweep list specifying thresholds for each condition
sweep_list <- list(
  X1 = 6:7,
  X2 = 6:7,
  X3 = 6:7
)

res_mcts <- ctSweepM(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_list     = sweep_list,
  thrY           = 7,
  dir.exp        = c(1, 1, 1),
  return_details = TRUE
)

summary(res_mcts)
#> MCTS-QCA Summary
#> ================ 
#> 
#> Analysis Parameters:
#>   Outcome: Y 
#>   Conditions: X1, X2, X3 
#>   Consistency cutoff: 0.8 
#>   Frequency cutoff: 1 
#> 
#> Results by Threshold:
#> 
#>         threshold combo_id     expression inclS  covS n_solutions
#>  X1=6, X2=6, X3=6        1          X1*X2 0.833 0.455           1
#>  X1=7, X2=6, X3=6        2          X1*X2 1.000 0.394           1
#>  X1=6, X2=7, X3=6        3      X1*X2*~X3 0.818 0.273           1
#>  X1=7, X2=7, X3=6        4          X1*X2 1.000 0.303           1
#>  X1=6, X2=6, X3=7        5             X3 0.864 0.576           1
#>  X1=7, X2=6, X3=7        6 ~X1*X3 + X1*X2 0.931 0.818           1
#>  X1=6, X2=7, X3=7        7             X3 0.864 0.576           1
#>  X1=7, X2=7, X3=7        8     X3 + X1*X2 0.906 0.879           1

Export:

write.csv(res_mcts$summary, file = "TSQCA_MCTS_results.csv", row.names = FALSE)

6. OTS–QCA (otSweep)

Sweep only the outcome threshold (Y).

sweep_range_ots <- 6:8

res_ots <- otSweep(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_range    = sweep_range_ots,
  thrX           = thrX_vec,
  dir.exp        = c(1, 1, 1),
  return_details = TRUE
)

summary(res_ots)
#> OTS-QCA Summary
#> =============== 
#> 
#> Analysis Parameters:
#>   Outcome: Y 
#>   Conditions: X1, X2, X3 
#>   Consistency cutoff: 0.8 
#>   Frequency cutoff: 1 
#> 
#> Results by Threshold:
#> 
#>  thrY  expression inclS  covS n_solutions
#>     6  X3 + X1*X2 0.906 0.853           1
#>     7  X3 + X1*X2 0.906 0.879           1
#>     8 No solution    NA    NA           0

Export:

write.csv(res_ots$summary, file = "TSQCA_OTS_results.csv", row.names = FALSE)

7. DTS–QCA (dtSweep)

Two-dimensional sweep: X thresholds × Y thresholds.

sweep_list_dts_X <- list(
  X1 = 6:7,
  X2 = 6:7,
  X3 = 6:7
)

sweep_range_dts_Y <- 6:7

res_dts <- dtSweep(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_list_X   = sweep_list_dts_X,
  sweep_range_Y  = sweep_range_dts_Y,
  dir.exp        = c(1, 1, 1),
  return_details = TRUE
)

summary(res_dts)
#> DTS-QCA Summary
#> =============== 
#> 
#> Analysis Parameters:
#>   Outcome: Y 
#>   Conditions: X1, X2, X3 
#>   Consistency cutoff: 0.8 
#>   Frequency cutoff: 1 
#> 
#> Results by Threshold:
#> 
#>  thrY combo_id             thrX     expression inclS  covS n_solutions
#>     6        1 X1=6, X2=6, X3=6          X1*X2 0.833 0.441           1
#>     7        1 X1=6, X2=6, X3=6          X1*X2 0.833 0.455           1
#>     6        2 X1=7, X2=6, X3=6          X1*X2 1.000 0.382           1
#>     7        2 X1=7, X2=6, X3=6          X1*X2 1.000 0.394           1
#>     6        3 X1=6, X2=7, X3=6      X1*X2*~X3 0.818 0.265           1
#>     7        3 X1=6, X2=7, X3=6      X1*X2*~X3 0.818 0.273           1
#>     6        4 X1=7, X2=7, X3=6          X1*X2 1.000 0.294           1
#>     7        4 X1=7, X2=7, X3=6          X1*X2 1.000 0.303           1
#>     6        5 X1=6, X2=6, X3=7             X3 0.864 0.559           1
#>     7        5 X1=6, X2=6, X3=7             X3 0.864 0.576           1
#>     6        6 X1=7, X2=6, X3=7 ~X1*X3 + X1*X2 0.931 0.794           1
#>     7        6 X1=7, X2=6, X3=7 ~X1*X3 + X1*X2 0.931 0.818           1
#>     6        7 X1=6, X2=7, X3=7             X3 0.864 0.559           1
#>     7        7 X1=6, X2=7, X3=7             X3 0.864 0.576           1
#>     6        8 X1=7, X2=7, X3=7     X3 + X1*X2 0.906 0.853           1
#>     7        8 X1=7, X2=7, X3=7     X3 + X1*X2 0.906 0.879           1

Export:

write.csv(res_dts$summary, file = "TSQCA_DTS_results.csv", row.names = FALSE)

8. Using extract_mode (New in v0.2.0)

Extract all solutions or essential prime implicants for robustness analysis.

Extract All Solutions

res_all <- otSweep(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_range    = 6:8,
  thrX           = thrX_vec,
  dir.exp        = c(1, 1, 1),
  extract_mode   = "all",
  return_details = TRUE
)

# View results with n_solutions column
head(res_all$summary)

Extract Essential Prime Implicants

res_essential <- otSweep(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_range    = 6:8,
  thrX           = thrX_vec,
  dir.exp        = c(1, 1, 1),
  extract_mode   = "essential",
  return_details = TRUE
)

# View results with essential prime implicants, selective terms, and unique terms
head(res_essential$summary)

9. Generating Reports (New in v0.2.0)

Create comprehensive markdown reports for documentation.

Full Report

generate_report(res_ots, "TSQCA_OTS_report_full.md", dat = dat, format = "full")

Simple Report (for manuscripts)

generate_report(res_ots, "TSQCA_OTS_report_simple.md", dat = dat, format = "simple")

10. Negated Outcome Analysis (New in v0.3.0)

Analyze conditions sufficient for the absence of the outcome.

Standard vs Negated Outcome

# Standard: conditions for Y >= threshold
res_Y <- otSweep(
  dat            = dat,
  outcome        = "Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_range    = 6:8,
  thrX           = thrX_vec,
  dir.exp        = c(1, 1, 1)
)

# Negated: conditions for Y < threshold
res_negY <- otSweep(
  dat            = dat,
  outcome        = "~Y",
  conditions     = c("X1", "X2", "X3"),
  sweep_range    = 6:8,
  thrX           = thrX_vec,
  dir.exp        = c(1, 1, 1)
)

# Compare results
res_Y$summary
res_negY$summary

# Check negation flag
res_negY$params$negate_outcome
# [1] TRUE

11. Accessing Analysis Parameters

All parameters are stored for reproducibility.

# View stored parameters
res_ots$params

# Example output:
# $outcome
# [1] "Y"
# $conditions
# [1] "X1" "X2" "X3"
# $thrX
# X1 X2 X3 
#  7  7  7 
# $incl.cut
# [1] 0.8
# $n.cut
# [1] 1
# $pri.cut
# [1] 0

Configuration Charts (New in v0.5.0)

Configuration charts are now automatically included in reports. You can also generate them separately:

# From path strings
paths <- c("A*B*~C", "A*D")
chart <- config_chart_from_paths(paths)
cat(chart)
#> | Condition | M1 | M2 |
#> |:--:|:--:|:--:|
#> | A | ● | ● |
#> | B | ● |  |
#> | C | ⊗ |  |
#> | D |  | ● |
#> 
#> *● = presence, ⊗ = absence, blank = don't care*

For reports:

# Charts are included by default
generate_report(result, "report.md", dat = dat, format = "full")

# Use LaTeX symbols for academic papers
generate_report(result, "report.md", dat = dat, chart_symbol_set = "latex")

References

For more information on TS-QCA methodology, see:

12. Session Information

sessionInfo()
#> R version 4.4.2 (2024-10-31 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#> 
#> Matrix products: default
#> 
#> 
#> locale:
#> [1] LC_COLLATE=C                    LC_CTYPE=Japanese_Japan.utf8   
#> [3] LC_MONETARY=Japanese_Japan.utf8 LC_NUMERIC=C                   
#> [5] LC_TIME=Japanese_Japan.utf8    
#> 
#> time zone: Asia/Tokyo
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] QCA_3.23    admisc_0.39 TSQCA_1.0.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] cli_3.6.5         knitr_1.50        rlang_1.1.6       xfun_0.55        
#>  [5] otel_0.2.0        promises_1.5.0    shiny_1.12.1      jsonlite_2.0.0   
#>  [9] xtable_1.8-4      htmltools_0.5.9   httpuv_1.6.16     sass_0.4.10      
#> [13] lpSolve_5.6.23    rmarkdown_2.30    evaluate_1.0.4    jquerylib_0.1.4  
#> [17] fastmap_1.2.0     yaml_2.3.10       lifecycle_1.0.4   compiler_4.4.2   
#> [21] Rcpp_1.1.0        rstudioapi_0.17.1 later_1.4.4       digest_0.6.39    
#> [25] R6_2.6.1          magrittr_2.0.4    bslib_0.9.0       declared_0.25    
#> [29] tools_4.4.2       mime_0.13         venn_1.12         cachem_1.1.0