knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
This document provides reproducible code for ThSQCA 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.
Note (v1.3.2): New Section 12 provides complete reproducible code for Fiss (2011) core/peripheral classification using
compute_fiss_core(),generate_fiss_chart(), andprint_fiss_summary().Note (v1.2.0): If you previously used intermediate solutions (with
dir.exp), please re-run your analyses. Version 1.2.0 fixed a bug where intermediate solutions were incorrectly extracted. Reports now also display the Solution Type and include optional QCA package output for verification.
library(ThSQCA) library(QCA)
# Adjust the file name as needed library(ThSQCA) data("sample_data") dat <- sample_data # Outcome and conditions outcome <- "Y" conditions <- c("X1", "X2", "X3") # Quick inspection str(dat) summary(dat)
thrY_base <- 7 thrX_base <- 7 # Fixed X thresholds (for OTS) thrX_vec <- c( X1 = thrX_base, X2 = thrX_base, X3 = thrX_base ) thrX_vec
As of v1.1.0, ThSQCA defaults match the QCA package:
| Solution Type | include | dir.exp | When to Use |
|--------------|-----------|-----------|-------------|
| Complex (default) | "" | NULL | Conservative analysis |
| Parsimonious | "?" | NULL | Maximum simplification |
| Intermediate | "?" | c(1,1,...) | Theory-driven (most common) |
# Example: Three solution types at single threshold thrX <- c(X1 = 7, X2 = 7, X3 = 7) # Complex (default) res_comp <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX) cat("Complex:", res_comp$summary$expression, "\n") # Parsimonious res_pars <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX, include = "?") cat("Parsimonious:", res_pars$summary$expression, "\n") # Intermediate res_int <- otSweep(dat, "Y", c("X1", "X2", "X3"), sweep_range = 7, thrX = thrX, include = "?", dir.exp = c(1, 1, 1)) cat("Intermediate:", res_int$summary$expression, "\n")
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) # Default: Complex solution (include = "", dir.exp = NULL) res_cts <- ctSweepS( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_var = "X3", sweep_range = 6:9, thrY = 7, thrX_default = 7, return_details = TRUE ) summary(res_cts)
# Intermediate solution: specify include = "?" and dir.exp res_cts_int <- ctSweepS( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_var = "X3", sweep_range = 6:9, thrY = 7, thrX_default = 7, include = "?", dir.exp = c(1, 1, 1), return_details = TRUE ) summary(res_cts_int)
Export:
write.csv(res_cts$summary, file = "ThSQCA_CTS_results.csv", row.names = FALSE)
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 ) # Default: Complex solution res_mcts <- ctSweepM( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_list = sweep_list, thrY = 7, return_details = TRUE ) summary(res_mcts)
# Intermediate solution: specify include = "?" and dir.exp res_mcts_int <- ctSweepM( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_list = sweep_list, thrY = 7, include = "?", dir.exp = c(1, 1, 1), return_details = TRUE ) summary(res_mcts_int)
Export:
write.csv(res_mcts$summary, file = "ThSQCA_CTS_multi_results.csv", row.names = FALSE)
Sweep only the outcome threshold (Y).
sweep_range_ots <- 6:8 # Default: Complex solution res_ots <- otSweep( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_range = sweep_range_ots, thrX = thrX_vec, return_details = TRUE ) summary(res_ots)
# Intermediate solution: specify include = "?" and dir.exp res_ots_int <- otSweep( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_range = sweep_range_ots, thrX = thrX_vec, include = "?", dir.exp = c(1, 1, 1), return_details = TRUE ) summary(res_ots_int)
Export:
write.csv(res_ots$summary, file = "ThSQCA_OTS_results.csv", row.names = FALSE)
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 # Default: Complex solution 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)
# Intermediate solution: specify include = "?" and dir.exp res_dts_int <- dtSweep( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_list_X = sweep_list_dts_X, sweep_range_Y = sweep_range_dts_Y, include = "?", dir.exp = c(1, 1, 1), return_details = TRUE ) summary(res_dts_int)
Export:
write.csv(res_dts$summary, file = "ThSQCA_DTS_results.csv", row.names = FALSE)
Extract all solutions or essential prime implicants for robustness analysis.
res_all <- otSweep( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_range = 6:8, thrX = thrX_vec, include = "?", # Include logical remainders dir.exp = c(1, 1, 1), # Intermediate solution extract_mode = "all", return_details = TRUE ) # View results with n_solutions column head(res_all$summary)
res_essential <- otSweep( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_range = 6:8, thrX = thrX_vec, include = "?", # Include logical remainders dir.exp = c(1, 1, 1), # Intermediate solution extract_mode = "essential", return_details = TRUE ) # View results with essential prime implicants, selective terms, and unique terms head(res_essential$summary)
Create comprehensive markdown reports for documentation.
generate_report(res_ots, "ThSQCA_OTS_report_full.md", dat = dat, format = "full")
generate_report(res_ots, "ThSQCA_OTS_report_simple.md", dat = dat, format = "simple")
Analyze conditions sufficient for the absence of the outcome.
# Standard: conditions for Y >= threshold (intermediate solution) res_Y <- otSweep( dat = dat, outcome = "Y", conditions = c("X1", "X2", "X3"), sweep_range = 6:8, thrX = thrX_vec, include = "?", # Include logical remainders dir.exp = c(1, 1, 1) # Intermediate solution ) # Negated: conditions for Y < threshold (intermediate solution) res_negY <- otSweep( dat = dat, outcome = "~Y", conditions = c("X1", "X2", "X3"), sweep_range = 6:8, thrX = thrX_vec, include = "?", # Include logical remainders dir.exp = c(1, 1, 1) # Intermediate solution ) # Compare results res_Y$summary res_negY$summary # Check negation flag res_negY$params$negate_outcome # [1] TRUE
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 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)
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")
For more information on ThS-QCA methodology, see:
This section provides fully reproducible code for Fiss-style four-symbol
configuration charts. Run sections 1–6 first to ensure res_ots_int is available.
# Requires: include = "?", dir.exp specified, return_details = TRUE # res_ots_int was created in Section 6 above. res_fiss <- compute_fiss_core( res_ots_int, conditions = c("X1", "X2", "X3") ) # Inspect available thresholds names(res_fiss$fiss_core)
# English print_fiss_summary(res_fiss, thr_key = "7") # Japanese print_fiss_summary(res_fiss, thr_key = "7", language = "ja")
Output (ThSQCA 2.0.8, QCA 3.25):
=== Fiss Core/Peripheral Classification (thrY = 7) === Parsimonious : X3 + X1*X2 Intermediate : X3 + X1*X2 [Term T1] X3 Core present : X3 [Term T2] X1*X2 Core present : X1, X2
Here the parsimonious and intermediate solutions coincide, so every condition
is core. In general, each term of the intermediate solution is compared with
the parsimonious term(s) contained in it: their conditions are core and the
other conditions of the term are peripheral, as in the solution tables of
Fiss (2011). See the section "Relation to Fiss (2011)" in
?compute_fiss_core for tied parsimonious solutions and other details.
compute_fiss_core() accepts results of otSweep() and ctSweepS().
# Unicode (Markdown / screen) cat(generate_fiss_chart(res_fiss, symbol_set = "unicode")) # LaTeX (for PDF/journal submission) cat(generate_fiss_chart(res_fiss, symbol_set = "latex")) # ASCII (maximum compatibility) cat(generate_fiss_chart(res_fiss, symbol_set = "ascii"))
Symbol legend:
| Symbol (unicode) | LaTeX | ASCII | Meaning |
|-----------------|-------|-------|---------|
| ● | $\bullet$ | O | Core condition present |
| ⊗ | $\otimes$ | X | Core condition absent |
| ⊙ | $\odot$ | o | Peripheral condition present |
| ⊘ | $\oslash$ | x | Peripheral condition absent |
| (blank) | (blank) | (blank) | Don't care |
# Full report with Fiss four-symbol charts generate_report( res_fiss, output_file = "ThSQCA_Fiss_report.md", format = "full", dat = dat, include_fiss_core = TRUE, # activates four-symbol charts chart_symbol_set = "unicode", include_raw_output = TRUE )
# Access raw classification data frame for a given threshold classif_7 <- res_fiss$fiss_core[["7"]]$classification classif_7 # Filter core conditions only classif_7[classif_7$type == "core" & classif_7$status != "dontcare", ] # Filter peripheral conditions only classif_7[classif_7$type == "peripheral" & classif_7$status != "dontcare", ] # Parsimonious and intermediate expressions res_fiss$fiss_core[["7"]]$parsim_expression res_fiss$fiss_core[["7"]]$interm_expression
compute_fiss_core() runs QCA::minimize() once per threshold (to count
the tied parsimonious solutions, and as a fallback when the stored solution
does not record its derivation). The total computation time is therefore
approximately double that of the original sweep. For large sweeps
(many thresholds or conditions), this is worth keeping in mind.
sessionInfo()
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.