Sufficient Condition Analysis (SCA) in R.
A condition is sufficient for an outcome when having the condition guarantees the outcome. In data, a sufficiency claim makes a definite prediction: the cases that would contradict it do not occur. Plot the condition X against the outcome Y and those cases sit in one corner of the scatter plot. “High X is sufficient for high Y” predicts that the lower-right corner – high X with low Y – is empty.
Sufficient Condition Analysis estimates that empty corner. It fits the boundary of the empty space, measures how large the empty space is, tests whether it is larger than random pairing of X and Y would produce, and turns the boundary into thresholds: the level of X that guarantees each level of Y.
A sufficiency claim can run in four directions, and each predicts a different empty corner:
| Direction | Claim | Empty corner |
|---|---|---|
HH |
high X is sufficient for high Y | lower-right |
LH |
low X is sufficient for high Y | lower-left |
HL |
high X is sufficient for low Y | upper-right |
LL |
low X is sufficient for low Y | upper-left |
You state the claim; the package finds the corner.
sca_compare() reports both side by side, so a study can say
which of the two its data show.sca_power()
estimates how many observations a sufficiency effect of a given size
needs.install.packages("SCAtools")The package includes four simulated datasets that show the four ways a regression effect and a sufficiency effect can combine.
library(SCAtools)
# Configuration II: a flat regression slope, but an empty lower-right corner
dat <- subset(sca_four_configurations, configuration == "II")
# 1. Fit the claim "high X is sufficient for high Y"
fit <- sca_analysis(dat, x = "X", y = "Y", direction = "HH",
scope = c(0, 100, 0, 100), test.rep = 1000)
fit # summary, with every setting the result rests on
# 2. Read the results
sca_table(fit) # effect size, p value and support for each condition
sca_thresholds(fit) # the X level that guarantees each Y level
sca_plot(fit) # the scatter plot, the frontier and the empty corner
# 3. Set it beside regression
sca_compare(fit) # here: slope near zero, large sufficiency effectsca() runs the same analysis with a permutation test and
draws the plot in one step:
sca(dat, x = "X", y = "Y", direction = "HH")| Function | What it shows |
|---|---|
sca_test_plot() |
the permutation distribution beside the observed effect size |
sca_scope() |
the scope each effect size was divided by |
sca_scope_sensitivity() |
how the effect size changes with the scope |
sca_resample() |
how much the effect size varies across subsamples |
sca_outliers() |
which observations hold up the frontier |
sca_locationshift() |
whether the frontier is a level shift or a threshold |
sca_magnitude() |
conventional bands for an effect size |
Effect size is the empty area as a share of the
scope, from 0 (no empty corner) to 1. effect_size_null
beside it is the value random pairing alone produces with the same
data.
p value comes from a permutation test that breaks the pairing of X and Y.
Thresholds read as rules such as
X > 38.9 => Y > 30. no_threshold
marks an outcome level that no value of X reaches;
always_satisfied marks one that every observation in scope
already meets.
Scales. A fitted model can be re-expressed without refitting:
sca_thresholds(fit, scale = "actual") # original units
sca_thresholds(fit, scale = "percentile") # percentiles
sca_thresholds(fit, scale = "sd") # standard deviationsUnder the default absolute convention 0 is the low end
of every axis and the inequality carries the direction; under
directional a low-level axis is mirrored so that every rule
reads as “more of the sufficient condition”. sca_scales()
lists the options.
sca_scope() and the printed
Settings block record it."ce_fdh") follows the data
as a step function; CR-FDH ("cr_fdh") fits a straight line
through it. 1000 or more permutations are usual.relevance = if a minimum effect size matters for the
conclusion.An ordinary least-squares or median regression line can be added with
reference = "ols" or "qr". It is drawn for
comparison and reported by sca_reference(); it is not part
of the sufficiency analysis.
?SCAtools describes the method and gives its
references.citation("SCAtools") gives the references to cite.system.file("docs", "sufficiency-logic.md", package = "SCAtools")
derives the four directions step by step, and
system.file("examples", "four-directions.R", package = "SCAtools")
runs them.Source and issue tracker: https://github.com/youngchanresearcher/SCAtools
The Traditional Chinese version of this README is installed with the package:
file.show(system.file("docs", "README_zh-TW.md", package = "SCAtools"))