TSQCA is an R package implementing Threshold-Sweep QCA
(TS-QCA),
a framework for systematically varying the thresholds used to
binarize
the outcome and conditions in crisp-set QCA.
After calibration, QCA results may change depending on how thresholds
are set.
TS-QCA evaluates this sensitivity by automatically:
QCA::minimize()Implemented sweep types:
Scope: TSQCA focuses on sufficiency analysis. Necessity analysis is planned for future versions.
As of v1.1.0, TSQCA uses the same defaults as
QCA::minimize():
| Solution Type | include |
dir.exp |
Logical Remainders | Description |
|---|---|---|---|---|
| Complex (default) | "" |
NULL |
Not used | Most conservative |
| Parsimonious | "?" |
NULL |
All used | Most simplified |
| Intermediate | "?" |
c(1,1,...) |
Theory-guided | Most common in publications |
data(sample_data)
thrX <- c(X1 = 7, X2 = 7, X3 = 7)
# 1. Complex Solution (default)
result_comp <- otSweep(dat = sample_data, outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 7, thrX = thrX)
# 2. Parsimonious Solution
result_pars <- otSweep(dat = sample_data, outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 7, thrX = thrX,
include = "?")
# 3. Intermediate Solution (most common in publications)
result_int <- otSweep(dat = sample_data, outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 7, thrX = thrX,
include = "?", dir.exp = c(1, 1, 1))Migration from v1.0.0: The default has changed from intermediate to complex solution. To reproduce v1.0.0 behavior, explicitly specify
include = "?"anddir.exp = c(1, 1, 1).
QCA minimization can produce multiple equivalent intermediate solutions. TSQCA detects and reports these cases, allowing researchers to identify robust essential prime implicants versus solution-specific selective prime implicants.
Use the extract_mode parameter to control output:
| Mode | Description | Use Case |
|---|---|---|
"first" |
Returns only the first solution (M1) | Default, backward compatible |
"all" |
Returns all solutions concatenated | See all equivalent solutions |
"essential" |
Returns essential prime implicants common to all solutions | Identify robust findings |
# Detect and show all solutions
result <- otSweep(
dat = mydata,
outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 6:8,
thrX = c(X1 = 7, X2 = 7, X3 = 7),
extract_mode = "all" # Show all solutions
)
# Extract essential prime implicants only
result_essential <- otSweep(
dat = mydata,
outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 6:8,
thrX = c(X1 = 7, X2 = 7, X3 = 7),
extract_mode = "essential" # Show essential prime implicants
)The generate_report() function creates comprehensive
markdown reports:
# Run analysis with return_details = TRUE (the default)
result <- otSweep(
dat = mydata,
outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_range = 6:8,
thrX = c(X1 = 7, X2 = 7, X3 = 7)
)
# Generate full report
generate_report(result, "my_analysis.md", dat = mydata, format = "full")
# Generate simple report (for journal manuscripts)
generate_report(result, "my_analysis_simple.md", dat = mydata, format = "simple")Reports include: - Analysis settings (for reproducibility) - Solution formulas with essential/selective prime implicants - Fit measures (consistency, coverage, PRI) - Cross-threshold comparison tables
Configuration charts are automatically included in reports. Generate Fiss-style configuration charts (Table 5 format):
# Reports include configuration charts by default
generate_report(result, "my_report.md", dat = mydata, format = "full")
# Disable charts if needed
generate_report(result, "my_report.md", dat = mydata, include_chart = FALSE)
# Use LaTeX symbols for academic papers
generate_report(result, "my_report.md", dat = mydata, chart_symbol_set = "latex")Standalone chart functions are also available:
# From path strings
paths <- c("A*B*~C", "A*D")
chart <- config_chart_from_paths(paths)
cat(chart)Output:
| Condition | M1 | M2 |
|:--:|:--:|:--:|
| A | ● | ● |
| B | ● | |
| C | ⊗ | |
| D | | ● |
Three symbol sets available: "unicode" (● / ⊗),
"ascii" (O / X), "latex" (\(\bullet\) / \(\otimes\))
All sweep functions return objects supporting S3 class methods:
print(): Display analysis overview with solution
statisticssummary(): Display full results table with
parametersresult <- otSweep(...)
print(result) # Quick overview
summary(result) # Full detailsAnalyze conditions sufficient for the absence of an outcome:
# Analyze when Y is low (below threshold)
result <- otSweep(
dat = mydata,
outcome = "~Y", # Tilde prefix for negation
conditions = c("X1", "X2", "X3"),
sweep_range = 6:9,
thrX = c(X1 = 7, X2 = 7, X3 = 7)
)TSQCA uses precise Boolean algebra terminology:
| Term | Meaning |
|---|---|
| Essential Prime Implicants (EPI) | Terms in ALL equivalent solutions (M1, M2…) |
| Selective Prime Implicants (SPI) | Terms in SOME solutions only |
Note: This is distinct from Fiss (2011) “Core Conditions” which compares parsimonious vs. intermediate solutions. See
docs/TSQCA_Terminology_Guide_EN.mdfor details.
install.packages("devtools")
devtools::install_github("im-research-yt/TSQCA")TSQCA is built on top of the QCA package (Duşa, 2019). All function arguments follow QCA conventions:
incl.cut, n.cut,
pri.cut → See QCA::truthTable()
include, dir.exp → See
QCA::minimize()
# Check QCA parameter documentation
?QCA::truthTable # For incl.cut, n.cut, pri.cut
?QCA::minimize # For include, dir.exp
# TSQCA uses these same parameters
result <- dtSweep(
dat = sample_data,
outcome = "Y",
conditions = c("X1", "X2"),
sweep_list_X = list(X1 = 6:7, X2 = 6:7),
sweep_range_Y = 6:7,
incl.cut = 0.8, # QCA parameter
n.cut = 1, # QCA parameter
pri.cut = 0 # QCA parameter
)library(QCA)
library(TSQCA)
dat <- read.csv("sample_data.csv", fileEncoding = "UTF-8")
outcome <- "Y"
conditions <- c("X1", "X2", "X3")
str(dat)When your dataset contains both continuous and binary (0/1) variables, special attention is needed:
sweep_listThe qca_bin() function uses x >= thr for
binarization: - If x = 0: 0 >= 1 → FALSE →
0 (preserved) - If x = 1:
1 >= 1 → TRUE → 1 (preserved)
# Suppose X1 is binary (0/1), while X2 and X3 are continuous (0-10)
sweep_list <- list(
X1 = 1, # Binary variable: use threshold 1 to preserve values
X2 = 6:8, # Continuous: sweep thresholds
X3 = 6:8 # Continuous: sweep thresholds
)
res_mcts <- ctSweepM(
dat = dat,
outcome = "Y",
conditions = c("X1", "X2", "X3"),
sweep_list = sweep_list,
thrY = 7
)This explores 1 × 3 × 3 = 9 threshold combinations, treating X1 as a fixed binary condition.
# WRONG: Using sweep range for binary variables
sweep_list <- list(
X1 = 6:8, # All values become 0 (since 0 < 6 and 1 < 6)
X2 = 6:8,
X3 = 6:8
)Best Practice: Always specify thresholds explicitly for each variable based on its data type.
sweep_var <- "X3" # Condition (X) whose threshold will be varied
sweep_range <- 6:9 # Candidate threshold values
thrY <- 7 # Fixed threshold for Y
thrX_default <- 7 # Fixed thresholds for other X's
res_cts <- ctSweepS(
dat = dat,
outcome = outcome,
conditions = conditions,
sweep_var = sweep_var, # X to sweep
sweep_range = sweep_range, # Threshold candidates for X
thrY = thrY, # Fixed Y threshold
thrX_default = thrX_default # Fixed thresholds for other X's
)
summary(res_cts)# Threshold candidates for each X
sweep_list <- list(
X1 = 6:7,
X2 = 6:7,
X3 = 6:7
)
res_mcts <- ctSweepM(
dat = dat,
outcome = outcome,
conditions = conditions,
sweep_list = sweep_list, # Threshold candidates for each X
thrY = 7 # Fixed Y threshold
)
summary(res_mcts)thrX <- c(X1 = 7, X2 = 7, X3 = 7) # Fixed thresholds for X
sweep_range_Y <- 6:8 # Candidate thresholds for Y
res_ots <- otSweep(
dat = dat,
outcome = outcome,
conditions = conditions,
sweep_range = sweep_range_Y, # Y threshold candidates
thrX = thrX # Fixed X thresholds
)
summary(res_ots)
# Generate report for detailed analysis
generate_report(res_ots, "ots_report.md", dat = dat, format = "full")# X-side threshold candidates (multiple conditions)
sweep_list_X <- list(
X1 = 6:7,
X2 = 6:7,
X3 = 6:7
)
# Y-side threshold candidates
sweep_range_Y <- 6:7
res_dts <- dtSweep(
dat = dat,
outcome = outcome,
conditions = conditions,
sweep_list_X = sweep_list_X, # X threshold candidates
sweep_range_Y = sweep_range_Y # Y threshold candidates
)
summary(res_dts)data(sample_data)
str(sample_data)This package implements methods developed in research supported by JSPS KAKENHI Grant Number JP20K01998.
MIT License.