cna {cna} | R Documentation |
Perform Coincidence Analysis
Description
The cna
function performs Coincidence Analysis to identify atomic solution formulas (asf) consisting of minimally necessary
disjunctions of minimally sufficient conditions of all outcomes in the data
and combines the recovered asf to complex solution formulas (csf) representing multi-outcome structures, e.g. common-cause and/or
causal chain structures.
Usage
cna(x, type, ordering = NULL, strict = FALSE, outcome = TRUE, exclude = character(0),
con = 1, cov = 1, con.msc = con,
notcols = NULL, rm.const.factors = FALSE, rm.dup.factors = FALSE,
maxstep = c(3, 4, 10), inus.only = only.minimal.msc && only.minimal.asf,
only.minimal.msc = TRUE, only.minimal.asf = TRUE,
maxSol = 1e6, suff.only = FALSE,
what = if (suff.only) "m" else "ac", cutoff = 0.5,
border = c("up", "down", "drop"), details = FALSE,
acyclic.only = FALSE, cycle.type = c("factor", "value"),
asf.selection = c("cs", "fs", "none"), verbose = FALSE)
## S3 method for class 'cna'
print(x, what = x$what, digits = 3, nsolutions = 5,
details = x$details, show.cases = NULL, inus.only = x$inus.only,
acyclic.only = x$acyclic.only, cycle.type = x$cycle.type,
verbose = FALSE, ...)
Arguments
x |
Data frame or |
type |
Character vector specifying the type of |
ordering |
Character string or list of character vectors specifying the causal ordering of
the factors in |
strict |
Logical; if |
outcome |
Character vector specifying one or several factor values that are to be considered as potential outcome(s). For crisp- and fuzzy-set data, factor values are expressed by upper and lower cases, for multi-value data, they are expressed by the "factor=value" notation.
Defaults to |
exclude |
Character vector specifying factor values to be excluded as possible causes of certain outcomes. For instance, |
con |
Numeric scalar between 0 and 1 to set the minimum consistency threshold every minimally sufficient condition (msc), atomic solution formula (asf), and complex solution formula (csf) must satisfy. (See also the argument |
cov |
Numeric scalar between 0 and 1 to set the minimum coverage threshold every asf and csf must satisfy. |
con.msc |
Numeric scalar between 0 and 1 to set the minimum consistency threshold every msc must satisfy. Overrides |
maxstep |
Vector of three integers; the first specifies the maximum number of conjuncts in each disjunct of an asf, the second specifies the maximum number of disjuncts in an asf, the third specifies the maximum complexity of an asf. The complexity of an asf is
the total number of exogenous factor values in the asf. Default: |
inus.only |
Either |
only.minimal.msc |
Logical; if |
only.minimal.asf |
Logical; if |
maxSol |
Maximum number of asf calculated. |
suff.only |
Logical; if |
notcols |
Character vector of factors to be negated in |
rm.const.factors , rm.dup.factors |
Logical; if |
what |
Character string specifying what to print; |
cutoff |
Minimum membership score required for a factor to count as instantiated in the data and to be integrated in the analysis. Value in the unit interval [0,1]. The default cutoff is 0.5. Only meaningful if |
border |
Character string specifying whether factors with membership scores equal to |
details |
Either |
acyclic.only |
Logical; if |
cycle.type |
Character string specifying what type of cycles to be detected: |
asf.selection |
Character string specifying how to select asfs based on outcome variation in configurations incompatible with a model. |
verbose |
Logical; if |
digits |
Number of digits to print in consistency, coverage, exhaustiveness, faithfulness, and coherence scores. |
nsolutions |
Maximum number of msc, asf, and csf to print. Alternatively, |
show.cases |
Logical; if |
... |
In |
Details
The first input x
of the cna
function is a data frame or a configuration table. To ensure that no misinterpretations of returned asf and csf can occur, users are advised to use only upper case letters as factor (column) names. Column names may contain numbers, but the first sign in a column name must be a letter. Only ASCII signs should be used for column and row names.
The argument type
allows for specifying the type of data x
contains. As of package version 3.2, that argument has the default value "auto"
inducing automatic detection of the data type. But the user can still manually set the data type. Data that feature factors taking values 1 or 0 only are called crisp-set, which can be indicated by type = "cs"
. If the data contain at least one factor that takes more than two values, e.g. {1,2,3}, the data count as multi-value: type = "mv"
. Data featuring at least one factor taking real values from the interval [0,1] count as fuzzy-set: type = "fs"
. (Note that mixing multi-value and fuzzy-set factors in one analysis is not supported).
A data frame or configuration table x
is the only mandatory input of the cna
function. In particular, cna
does not need an input specifying which factor(s) in x
are endogenous, it tries to infer that from the data. But if it is known prior to the analysis what factors have values that can figure as outcomes, an outcome specification can be given to cna
via the argument outcome
, which takes as input a character vector identifying one or several factor values as potential outcome(s). For "cs"
and "fs"
data, outcomes are expressed by upper and lower cases (e.g. outcome = c("A", "b")
). If factor names have multiple letters, any upper case letter is interpreted as 1, and the absence of upper case letters as 0 (i.e. outcome = c("coLd", "shiver")
is interpreted as COLD=1
and SHIVER=0
). For "mv"
data, factor values are assigned by the “factor=value” notation (e.g. outcome = c("A=1","B=3")
). Defaults to outcome = TRUE
, which means that all factor values in x
are potential outcomes.
When the data x
contain multiple potential outcomes, it may moreover be known, prior to the analysis, that these outcomes have a certain causal ordering, meaning that some of them are causally upstream of the others. Such information can be given to cna
by means of the argument ordering
, which takes either a character string or a list of character vectors as value.
For example, ordering = "A, B < C"
or, equivalently, ordering = list(c("A",
"B"), "C")
determines that factor C is causally located downstream of factors A and B, meaning that no values of C are potential causes of values of A and B. In consequence, cna
only checks whether values of A and B can be modeled as causes of values of C; the test for a causal dependency in the other direction is skipped.
An ordering
does not need to explicitly mention all factors in x
. If only a subset of the factors are included in the ordering
, the non-included factors are entailed to be upstream of the included ones. Hence, ordering = "C"
means that C is located downstream of all other factors in x
.
The argument strict
determines whether the elements of one level in an ordering can be causally related or not. For example, if ordering = "A, B < C"
and strict = TRUE
, then the values of A and B—which are on the same level of the ordering—are excluded to be causally related and cna
skips corresponding tests. By contrast, if ordering = "A, B < C"
and strict = FALSE
, then cna
also searches for dependencies among the values of A and B. The default is strict
= FALSE
.
An ordering
excludes all values of a factor as potential causes of an outcome. But a user may only be in a position to exclude some (not all) values as potential causes. Such information can be given to cna
through the argument exclude
, which can be assigned a vector of character strings featuring the factor values to be excluded as causes to the left of the "->
" sign and the corresponding outcomes on the right. For example, exclude = "A=1,C=3 -> B=1"
determines that the value 1 of factor A and the value 3 of factor C are excluded as causes of the value 1 of factor B. Factor values can be excluded as potential causes of multiple outcomes as follows: exclude = c("A,c -> B", "b,H -> D")
. For "cs"
and "fs"
data, upper case letters are interpreted as 1, lower case letters as 0. If factor names have multiple letters, any upper case letter is interpreted as 1, and the absence of upper case letters as 0. For "mv"
data, the "factor=value" notation is required.
To exclude all values of a factor as potential causes of an outcome or to exclude a factor value as potential cause of all values of some endogenous factor, a "*
" can be appended to the corresponding factor name; for example: exclude = "A* -> B"
or exclude = "A=1,C=3 -> B*"
.
The exclude
argument can be used both independently of and in conjunction with outcome
and ordering
, but if assignments to outcome
and ordering
contradict assignments to exclude
, the latter are ignored. If exclude
is assigned values of factors that do not appear in the data x
, an error is returned.
If no outcomes are specified and no causal ordering is provided, all factor values in x
are treated as potential outcomes; more specifically, in case of "cs"
and "fs"
data, cna
tests for all factors whether their presence (i.e. them taking the value 1) can be modeled as an outcome, and in case of "mv"
data, cna
tests for all factors whether any of their possible values can be modeled as an outcome. That is done by searching for redundancy-free Boolean functions (in disjunctive normal form) that account for the behavior of an outcome in accordance with exclude
and cna
's core model fit parameters of consistency and coverage (for details see the cna package vignette or Ragin 2006). First, cna
identifies all minimally sufficient conditions (msc) that meet the threshold given by the consistency threshold con.msc
(resp. con
, if con.msc = con
) for each potential outcome in x
. Then, these msc are disjunctively combined to minimally
necessary conditions that meet the coverage threshold given by cov
such that the whole disjunction meets the solution consistency threshold given by con
. The resulting expressions are the atomic solution formulas (asf) for every factor value that can be modeled as outcome. The default value for con.msc
, con
, and cov
is 1.
The cna
function builds its models in four stages using a bottom-up search algorithm (see Baumgartner and Ambuehl 2020).
- First stage
On the basis of
outcome
andordering
, the algorithm builds a set of potential outcomes O from the factors inx
; and on the basis ofordering
andexclude
, it assigns a set of potential causes to each potential outcome. At the default values ofoutcome
,ordering
, andexclude
, all factor values inx
are treated as potential outcomes and as potential causes.- Second stage
The algorithm checks whether single factor values, e.g. A, b, C, (where "A" stands for "A=1" and "b" for "B=0") or D=3, E=2, etc., (whose membership scores, in case of
"fs"
data, meetcutoff
in at least one case) are sufficient for a potential outcome in O (where a factor value counts as sufficient iff it meets the threshold given bycon.msc
). Next, conjuncts of two factor values, e.g. A*b, A*C, D=3*E=2 etc., (whose membership scores, in case of"fs"
data, meetcutoff
in at least one case) are tested for sufficiency. Then, conjuncts of three factors, and so on. Whenever a conjunction (or a single factor value) is found to be sufficient, all supersets of that conjunction contain redundancies and are, thus, not considered for the further analysis. The result is a set of msc for every potential outcome in O. To recover certain target structures from noisy data, it may be useful to allowcna
to also consider sufficient conditions for further analysis that are not minimal. This can be accomplished by settingonly.minimal.msc
toFALSE
. A concrete example illustrating the utility ofonly.minimal.msc
is provided in the “Examples” section below. (The ordinary user is advised not to change the default value of this argument.)- Third stage
Minimally necessary disjunctions are built for each potential outcome in O by first testing whether single msc are necessary, then disjunctions of two msc, then of three, etc. (where a disjunction of msc counts as necessary iff it meets the threshold given by
cov
). Whenever a disjunction of msc (or a single msc) is found to be necessary, all supersets of that disjunction contain redundancies and are, thus, excluded from the further analysis. Finally, all and only those disjunctions of msc that meet bothcov
andcon
are issued as redundancy-free atomic solution formulas (asf). To recover certain target structures from noisy data, it may be useful to allowcna
to also consider necessary conditions for further analysis that are not minimal. This can be accomplished by settingonly.minimal.asf
toFALSE
, in which case all disjunctions of msc reaching the con and cov thresholds will be returned. (The ordinary user is advised not to change the default value of this argument.)As the combinatorial search space for asf is potentially too large to be exhaustively scanned in reasonable time, the argument
maxstep
allows for setting an upper bound for the complexity of the generated asf.maxstep
takes a vector of three integersc(i, j, k)
as input, entailing that the generated asf have maximallyj
disjuncts with maximallyi
conjuncts each and a total of maximallyk
factor values (k
is the maximal complexity). The default ismaxstep = c(3, 4, 10)
.Note that when the data feature noise due to uncontrolled background influences the default
con
andcov
thresholds of 1 will often not yield any asf. In such cases,con
andcov
may be set to values different from 1.con
andcov
should neither be set too high, in order to avoid overfitting, nor too low, in order to avoid underfitting. The overfitting danger is severe in causal modeling with CNA (and configurational causal modeling more generally). For a discussion of this problem see Parkkinen and Baumgartner (2023), who also introduce a procedure for robustness assessment that explores all threshold settings in a given interval—in an attempt to reduce both over- and underfitting. See also the R package frscore.- Fourth stage
If
cna
finds asf, it builds complex solution formulas (csf) from those asf. This is done in a stepwise manner as follows. First, all logically possible conjunctions featuring one asf of every outcome are built. Second, ifinus.only = TRUE
, the solutions resulting from step 1 are freed of structural redundancies (cf. Baumgartner and Falk 2023), and tautologous and contradictory solutions as well as solutions with partial structural redundancies and constant factors are eliminated (cf.is.inus
). [Note: as of package version 3.6.0, the "implication" definition of partial structural redundancy is used, seeis.inus
for details.] Third, ifacyclic.only = TRUE
, solutions with cyclic substructures are eliminated. Fourth, for those solutions that were modified in the previous steps, consistency and coverage are re-calculated and solutions that no longer reachcon
orcov
are eliminated. The remaining solutions are returned as csf. (See alsocsf
.)
If verbose
is set to its non-default value TRUE
, some information about the progression of the algorithm is returned to the console during the execution of the cna
function. The execution can easily be interrupted by ESC at all stages.
The default output of cna
lists asf and csf, ordered by complexity and the product of consistency and coverage. It provides the consistency and coverage scores of each solution, a complexity score, which corresponds to the number of exogenous factor values in a solution, and a column “inus
” indicating whether a solution has INUS form, meaning whether it is redundancy-free as required by the INUS-theory of causation (Mackie 1974, ch. 3; Baumgartner and Falk 2023). If inus.only = TRUE
, all solutions automatically have INUS form, but if only.minimal.msc
or
only.minimal.asf
are set to FALSE
, non-INUS solutions may also be returned.
Apart from the standard solution attributes, cna
can calculate a number of further solution attributes: exhaustiveness
, faithfulness
, coherence
, redundant
, and cyclic
all of which are recovered by setting details
to its non-default value TRUE
or to a character vector specifying the attributes to be calculated.
These attributes require explication (see also vignette("cna")
):
-
exhaustiveness
andfaithfulness
are two measures of model fit that quantify the degree of correspondence between the configurations that are, in principle, compatible with a solution and the configurations contained in the data from which that solution is derived.-
exhaustiveness
amounts to the ratio of the number of configurations in the data that are compatible with a solution to the number of configurations in total that are compatible with a solution. -
faithfulness
amounts to the ratio of the number of configurations in the data that are compatible with a solution to the total number of configurations in the data.
-
-
coherence
measures the degree to which the asf combined in a csf cohere, i.e. are instantiated together in the data rather than independently of one another. For more details seecoherence
. -
redundant
determines whether a csf contains structurally redundant proper parts. A csf withredundant = TRUE
should not be causally interpreted. Ifinus.only = TRUE
, all csf are free of structural redundancies. For more details seeredundant
. -
cyclic
determines whether a csf contains a cyclic substructure. For more details seecyclic
.
The argument notcols
is used to calculate asf and csf
for negative outcomes in data of type
"cs"
and "fs"
(in "mv"
data notcols
has no meaningful interpretation and, correspondingly, issues an error message). If notcols = "all"
, all factors in x
are negated,
i.e. their membership scores i are replaced by 1-i. If notcols
is given a character vector
of factors in x
, only the factors in that vector are negated. For example, notcols = c("A", "B")
determines that only factors A and B are negated. The default is no negations, i.e. notcols = NULL
.
suff.only
is applicable whenever a complete cna
analysis cannot be performed for reasons of computational complexity. In such a case, suff.only = TRUE
forces cna
to stop the analysis after the identification of msc, which will normally yield results even in cases when a complete analysis does not terminate. In that manner, it is possible to shed at least some light on the dependencies among the factors in x
, in spite of an incomputable solution space.
rm.const.factors
and rm.dup.factors
are used to determine the handling of constant factors, i.e. factors with constant values in all cases (rows) in x
, and of duplicated factors, i.e. factors that take identical value distributions in all cases in x
. As of package version 3.5.4, the default is FALSE
for both rm.const.factors
and rm.dup.factors
. See configTable
for more details.
If the data x
feature noise, it can happen that all variation of an outcome occurs in noisy configurations in x
. In such cases, there may be asfs that meet chosen consistency and coverage thresholds (lower than 1) such that the corresponding outcome only varies in configurations that are incompatible with the strict crisp-set or fuzzy-set necessity and sufficiency relations expressed by those very asfs. In the default setting "cs"
of the argument asf.selection
(introduced in version 3.5.0 of the cna package), an asf is only returned if the outcome takes a value above and below the 0.5 anchor in the configurations compatible with the strict crisp-set necessity and sufficiency relations expressed by that asf. At asf.selection = "fs"
, an asf is only returned if the outcome takes different values in the configurations compatible with the strict fuzzy-set necessity and sufficiency relations expressed by that asf. At asf.selection = "none"
, asfs are returned even if outcome variation only occurs in noisy configurations, which was the default behavior of cna
prior to version 3.5.0. (For more details, see examples below.)
The argument what
can be specified both for the cna
and the print()
function. It regulates what items of the output of cna
are printed. If
what
is given the value “t
”, the configuration table is printed; if
it is given an “m
”, the msc are printed; if it is given an “a
”, the asf are printed; if it is given a “c
”, the csf are printed.
what = "all"
or what = "tmac"
determine that all output items are
printed. Note that what
has no effect on the computations that are performed when executing cna
; it only determines how the result is printed.
The default output of cna
is what = "ac"
. It first returns an implemented ordering or outcome specification. Second, the top 5 asf and, third, the top 5 csf are reported, along with an indication of how many solutions in total exist. To print all msc, asf, and csf, the corresponding functions in condTbl
should be used.
In case of suff.only = TRUE
, what
defaults to "m"
. msc are printed with an attribute minimal
specifying whether a sufficient condition is minimal as required by the INUS-theory of causation. If inus.only = TRUE
, all msc are minimal by default.
cna
only includes factor configurations in the analysis that are actually instantiated in the data. The argument cutoff
determines the minimum membership score required for a factor or a combination of factors to count as instantiated. It takes values in the unit interval [0,1] with a default of 0.5. border
specifies whether configurations with membership scores equal to cutoff
are rounded up (border = "up"
), which is the default, rounded down (border = "down"
), or dropped from the analysis (border = "drop"
).
The arguments digits
, nsolutions
, and show.cases
apply to the print()
method, which takes an object of class “cna” as first input. digits
determines how many digits of consistency, coverage, coherence, exhaustiveness, and faithfulness scores
are printed, while nsolutions
fixes the number of conditions and solutions
to print. nsolutions
applies separately to minimally sufficient conditions,
atomic solution formulas, and complex solution formulas. nsolutions = "all"
recovers all minimally sufficient conditions, atomic and complex solution formulas. show.cases
is applicable if the what
argument is given the value “t
”. In that case, show.cases = TRUE
yields a configuration table featuring a “cases” column, which assigns cases to configurations.
The option “spaces” controls how the conditions are rendered. The current setting is queried by typing getOption("spaces")
. The option specifies characters that will be printed with a space before and after them. The default is c("<->","->","+")
. A more compact output is obtained with option(spaces = NULL)
.
Value
cna
returns an object of class “cna”, which amounts to a list with the following elements:
call : | the executed function call |
x : | the processed data frame or configuration table, as input to cna |
ordering | the ordering imposed on the factors in the configuration table (if not NULL ) |
notcols | the names of negated outcome factors (if not NULL ) |
configTable : | the object of class “configTable” |
solution : | the solution object, which itself is composed of lists exhibiting msc, asf, |
and csf for all factors in x |
|
what : | the values given to the what argument |
details : | the calculated solution attributes |
... : | plus additional list elements reporting the values given to the parameters con , |
cov , con.msc , inus.only , acyclic.only , and cycle.type .
|
Note
In the first example described below (in Examples), the two resulting complex solution formulas represent a common cause structure and a causal chain, respectively. The common cause structure is graphically depicted in figure (a) below, the causal chain in figure (b).
References
Aleman, Jose. 2009. “The Politics of Tripartite Cooperation in New Democracies: A Multi-level Analysis.” International Political Science Review 30 (2):141-162.
Basurto, Xavier. 2013. “Linking Multi-Level Governance to Local Common-Pool Resource Theory using Fuzzy-Set Qualitative Comparative Analysis: Insights from Twenty Years of Biodiversity Conservation in Costa Rica.” Global Environmental Change 23(3):573-87.
Baumgartner, Michael. 2009a. “Inferring Causal Complexity.” Sociological Methods & Research 38(1):71-101.
Baumgartner, Michael and Mathias Ambuehl. 2020. “Causal Modeling with Multi-Value and Fuzzy-Set Coincidence Analysis.” Political Science Research and Methods. 8:526–542.
Baumgartner, Michael and Christoph Falk. 2023. “Boolean Difference-Making: A Modern Regularity Theory of Causation”. The British Journal for the Philosophy of Science, 74(1), 171-197.
Hartmann, Christof, and Joerg Kemmerzell. 2010. “Understanding Variations in Party Bans in Africa.” Democratization 17(4):642-65.
Krook, Mona Lena. 2010. “Women's Representation in Parliament: A Qualitative Comparative Analysis.” Political Studies 58(5):886-908.
Mackie, John L. 1974. The Cement of the Universe: A Study of Causation. Oxford: Oxford University Press.
Parkkinen, Veli-Pekka and Michael Baumgartner. 2023. “Robustness and Model Selection in Configurational Causal Modeling”, Sociological Methods & Research, 52(1), 176-208.
Ragin, Charles C. 2006. “Set Relations in Social Research: Evaluating Their Consistency and Coverage”. Political Analysis 14(3):291-310.
Wollebaek, Dag. 2010. “Volatility and Growth in Populations of Rural Associations.” Rural Sociology 75:144-166.
See Also
configTable
, condition
, cyclic
, condTbl
, selectCases
, makeFuzzy
, some
, coherence
,
minimalizeCsf
, randomConds
, is.submodel
, is.inus
, redundant
, full.ct
, shortcuts
, d.educate
,
d.women
, d.pban
, d.autonomy
, d.highdim
Examples
# Ideal crisp-set data from Baumgartner (2009a) on education levels in western democracies
# ----------------------------------------------------------------------------------------
# Exhaustive CNA without constraints on the search space; print atomic and complex
# solution formulas (default output).
cna.educate <- cna(d.educate)
cna.educate
# The two resulting complex solution formulas represent a common cause structure
# and a causal chain, respectively. The common cause structure is graphically depicted
# in (Note, figure (a)), the causal chain in (Note, figure (b)).
# Print only complex solution formulas.
print(cna.educate, what = "c")
# Print only atomic solution formulas.
print(cna.educate, what = "a")
# Print only minimally sufficient conditions.
print(cna.educate, what = "m")
# Print only the configuration table.
print(cna.educate, what = "t")
# CNA with negations of the factors E and L.
cna(d.educate, notcols = c("E","L"))
# The same by use of the outcome argument.
cna(d.educate, outcome = c("e","l"))
# CNA with negations of all factors.
cna(d.educate, notcols = "all")
# Print msc, asf, and csf with all solution attributes.
cna(d.educate, what = "mac", details = TRUE)
# Add only the non-standard solution attributes "exhaustiveness" and "faithfulness".
cna(d.educate, details = c("e", "f"))
# Print solutions without spaces before and after "+".
options(spaces = c("<->", "->" ))
cna(d.educate, details = c("e", "f"))
# Print solutions with spaces before and after "*".
options(spaces = c("<->", "->", "*" ))
cna(d.educate, details = c("e", "f"))
# Restore the default of the option "spaces".
options(spaces = c("<->", "->", "+"))
# Crisp-set data from Krook (2010) on representation of women in western-democratic parliaments
# ------------------------------------------------------------------------------------------
# This example shows that CNA can distinguish exogenous and endogenous factors in the data.
# Without being told which factor is the outcome, CNA reproduces the original QCA
# of Krook (2010).
ana1 <- cna(d.women, details = c("e", "f"))
ana1
# The two resulting asf only reach an exhaustiveness score of 0.438, meaning that
# not all configurations that are compatible with the asf are contained in the data
# "d.women". Here is how to extract the configurations that are compatible with
# the first asf but are not contained in "d.women".
library(dplyr)
setdiff(ct2df(selectCases(asf(ana1)$condition[1], full.ct(d.women))),
d.women)
# Highly ambiguous crisp-set data from Wollebaek (2010) on very high volatility of
# grassroots associations in Norway
# --------------------------------------------------------------------------------
# csCNA with ordering from Wollebaek (2010) [Beware: due to massive ambiguities, this analysis
# will take about 20 seconds to compute.]
cna(d.volatile, ordering = "VO2", maxstep = c(6, 6, 16))
# Using suff.only, CNA can be forced to abandon the analysis after minimization of sufficient
# conditions. [This analysis terminates quickly.]
cna(d.volatile, ordering = "VO2", maxstep = c(6, 6, 16), suff.only = TRUE)
# Similarly, by using the default maxstep, CNA can be forced to only search for asf and csf
# with reduced complexity.
cna(d.volatile, ordering = "VO2")
# ordering = "VO2" only excludes that the values of VO2 are causes of the values
# of the other factors in d.volatile, but cna() still tries to model other factor
# values as outcomes. The following call determines that only VO2 is a possible
# outcome. (This call terminates quickly.)
cna(d.volatile, outcome = "VO2")
# We can even increase maxstep.
cna(d.volatile, outcome = "VO2", maxstep=c(4,4,16))
# If it is known that, say, el and od cannot be causes of VO2, we can exclude this.
cna(d.volatile, outcome = "VO2", maxstep=c(4,4,16), exclude = "el, od -> VO2")
# The verbose argument returns information during the execution of cna().
cna(d.volatile, ordering = "VO2", verbose = TRUE)
# Multi-value data from Hartmann & Kemmerzell (2010) on party bans in Africa
# ---------------------------------------------------------------------------
# mvCNA with an outcome specification taken from Hartmann & Kemmerzell
# (2010); coverage cutoff at 0.95 (consistency cutoff at 1), maxstep at c(6, 6, 10).
cna.pban <- cna(d.pban, outcome = "PB=1", cov = .95, maxstep = c(6, 6, 10),
what = "all")
cna.pban
# The previous function call yields a total of 14 asf and csf, only 5 of which are
# printed in the default output. Here is how to extract all 14 asf and csf.
asf(cna.pban)
csf(cna.pban)
# [Note that all of these 14 causal models reach better consistency and
# coverage scores than the one model Hartmann & Kemmerzell (2010) present in their paper,
# which they generated using the TOSMANA software, version 1.3.
# T=0 + T=1 + C=2 + T=1*V=0 + T=2*V=0 <-> PB=1]
condTbl("T=0 + T=1 + C=2 + T=1*V=0 + T=2*V=0 <-> PB = 1", d.pban)
# Extract all minimally sufficient conditions.
msc(cna.pban)
# Alternatively, all msc, asf, and csf can be recovered by means of the nsolutions
# argument of the print function.
print(cna.pban, nsolutions = "all")
# Print the configuration table with the "cases" column.
print(cna.pban, what = "t", show.cases = TRUE)
# Build solution formulas with maximally 4 disjuncts.
cna(d.pban, outcome = "PB=1", cov = .95, maxstep = c(4, 4, 10))
# Only print 2 digits of consistency and coverage scores.
print(cna.pban, digits = 2)
# Build all but print only two msc for each factor and two asf and csf.
print(cna(d.pban, outcome = "PB=1", cov = .95,
maxstep = c(6, 6, 10), what = "all"), nsolutions = 2)
# Lowering the consistency instead of the coverage threshold yields further models with
# excellent fit scores; print only asf.
cna(d.pban, outcome = "PB=1", con = .93, what = "a", maxstep = c(6, 6, 10))
# Lowering both consistency and coverage.
cna(d.pban, outcome = "PB=1", con = .9, cov =.9, maxstep = c(6, 6, 10))
# Lowering both consistency and coverage and excluding F=0 as potential cause of PB=1.
cna(d.pban, outcome = "PB=1", con = .9, cov =.9, maxstep = c(6, 6, 10),
exclude = "F=0 -> PB=1")
# Specifying an outcome is unnecessary for d.pban. PB=1 is the only
# factor value in those data that could possibly be an outcome.
cna(d.pban, con=.9, cov = .9, maxstep = c(6, 6, 10))
# Fuzzy-set data from Basurto (2013) on autonomy of biodiversity institutions in Costa Rica
# ---------------------------------------------------------------------------------------
# Basurto investigates two outcomes: emergence of local autonomy and endurance thereof. The
# data for the first outcome are contained in rows 1-14 of d.autonomy, the data for the second
# outcome in rows 15-30. For each outcome, the author distinguishes between local ("EM",
# "SP", "CO"), national ("CI", "PO") and international ("RE", "CN", "DE") conditions. Here,
# we first apply fsCNA to replicate the analysis for the local conditions of the endurance of
# local autonomy.
dat1 <- d.autonomy[15:30, c("AU","EM","SP","CO")]
cna(dat1, ordering = "AU", strict = TRUE, con = .9, cov = .9)
# The fsCNA model has significantly better consistency (and equal coverage) scores than the
# model presented by Basurto (p. 580): SP*EM + CO <-> AU, which he generated using the
# fs/QCA software.
condition("SP*EM + CO <-> AU", dat1) # both EM and CO are redundant to account for AU
# If we allow for dependencies among the conditions by setting strict = FALSE, CNA reveals
# that SP is a common cause of both AU and EM.
cna(dat1, ordering = "AU", strict = FALSE, con = .9, cov = .9)
# Here is the analysis for the international conditions of autonomy endurance, which
# yields the same model as the one presented by Basurto (plus one model Basurto does not mention).
dat2 <- d.autonomy[15:30, c("AU","RE", "CN", "DE")]
cna(dat2, ordering = "AU", con = .9, con.msc = .85, cov = .85)
# But there are other models (here printed with all solution attributes)
# that fare equally well.
cna(dat2, ordering = "AU", con = .85, cov = .9, details = TRUE)
# Finally, here is an analysis of the whole dataset, showing that across the whole period
# 1986-2006, the best causal model of local autonomy (AU) renders that outcome dependent
# only on local direct spending (SP).
cna(d.autonomy, outcome = "AU", con = .85, cov = .9,
maxstep = c(5, 5, 11), details = TRUE)
# Also build non-INUS solutions.
asf(cna(d.autonomy, outcome = "AU", con = .85, cov = .9,
maxstep = c(5, 5, 11), details = TRUE, inus.only = FALSE))
# High-dimensional data
# ---------------------
# As of package version 3.1, cna's handling of data with more than 20 factors
# has been improved. Here's an analysis of the data d.highdim with 50 factors, massive
# fragmentation, and 20% noise. (Takes about 15 seconds to compute.)
head(d.highdim)
cna(d.highdim, outcome = c("V13", "V11"), con = .8, cov = .8)
# By lowering maxstep, computation time can be reduced to less than 1 second
# (at the cost of an incomplete solution).
cna(d.highdim, outcome = c("V13", "V11"), con = .8, cov = .8,
maxstep = c(2,3,10))
# Highly ambiguous artificial data to illustrate exhaustiveness and acyclic.only
# ------------------------------------------------------------------------------
mycond <- "(D + C*f <-> A)*(C*d + c*D <-> B)*(B*d + D*f <-> C)*(c*B + B*f <-> E)"
dat1 <- selectCases(mycond)
ana1 <- cna(dat1, details = c("e","cy"))
# There exist almost 2M csf. This is how to build the first 1076 of them, with
# additional messages about the csf building process.
first.csf <- csf(ana1, verbose = TRUE)
first.csf
# Most of these csf are compatible with more configurations than are contained in
# dat1. Only 193 csf in first.csf are perfectly exhaustive (i.e. all compatible
# configurations are contained in dat1).
subset(first.csf, exhaustiveness == 1)
# 1020 of the csf in first.csf contain cyclic substructures.
subset(first.csf, cyclic == TRUE)
# Here's how to only build acyclic csf.
ana2 <- cna(dat1, details = c("e","cy"), acyclic.only = TRUE)
csf(ana2, verbose = TRUE)
# Illustration of only.minimal.msc = FALSE
# ----------------------------------------
# Simulate noisy data on the causal structure "a*B*d + A*c*D <-> E"
set.seed(1324557857)
mydata <- allCombs(rep(2, 5)) - 1
dat1 <- makeFuzzy(mydata, fuzzvalues = seq(0, 0.5, 0.01))
dat1 <- ct2df(selectCases1("a*B*d + A*c*D <-> E", con = .8, cov = .8, dat1))
# In dat1, "a*B*d + A*c*D <-> E" has the following con and cov scores.
as.condTbl(condition("a*B*d + A*c*D <-> E", dat1))
# The standard algorithm of CNA will, however, not find this structure with
# con = cov = 0.8 because one of the disjuncts (a*B*d) does not meet the con
# threshold.
as.condTbl(condition(c("a*B*d <-> E", "A*c*D <-> E"), dat1))
cna(dat1, outcome = "E", con = .8, cov = .8)
# With the argument con.msc we can lower the con threshold for msc, but this does not
# recover "a*B*d + A*c*D <-> E" either.
cna2 <- cna(dat1, outcome = "E", con = .8, cov = .8, con.msc = .78)
cna2
msc(cna2)
# The reason is that "A*c -> E" and "c*D -> E" now also meet the con.msc threshold and,
# therefore, "A*c*D -> E" is not contained in the msc---because of violated minimality.
# In a situation like this, lifting the minimality requirement via
# only.minimal.msc = FALSE allows CNA to find the intended target.
cna(dat1, outcome = "E", con = .8, cov = .8, con.msc = .78,
only.minimal.msc = FALSE)
# Overriding automatic detection of the data type
# ------------------------------------------------
# The type argument allows for manually setting the data type.
# If "cs" data are treated as "mv" data, cna() automatically builds models for all values
# of outcome factors, i.e. both positive and negated outcomes.
cna(d.educate, type = "mv")
# Treating "cs" data as "fs".
cna(d.women, type = "fs")
# Not all manual settings are admissible.
try(cna(d.autonomy, outcome = "AU", con = .8, cov = .8, type = "mv" ))
# Shortcut functions from previous versions of the package continue to work
# (see ?shortcuts).
fscna(d.autonomy, outcome = "AU", con = .8, cov = .8)
mvcna(d.pban, outcome = "PB=1", con = .8)
# Illustration of asf.selection
# -----------------------------
# Consider the following data set:
d1 <- data.frame(X1 = c(1, 0, 1),
X2 = c(0, 1, 0),
Y = c(1, 1, 0))
ct1 <- configTable(d1, frequency = c(10, 10, 1))
# Both of the following are asfs reaching con=0.95 and cov=1.
condition(c("X1+X2<->Y", "x1+x2<->Y"), ct1)
# Up to version 3.4.0 of the cna package, these two asfs were inferred from
# ct1 by cna(). But the outcome Y is constant in ct1, except for a variation in
# the third row, which is incompatible with X1+X2<->Y and x1+x2<->Y. Subject to
# both of these models, the third row of ct1 is a noisy configuration. Inferring
# difference-making models that are incapable of accounting for the only difference
# in the outcome in the data is inadequate. (Thanks to Luna De Souter for
# pointing out this problem.) Hence, as of version 3.5.0, asfs whose outcome only
# varies in configurations incompatible with the strict crisp-set necessity
# or sufficiency relations expressed by those asfs are not returned anymore.
cna(ct1, outcome = "Y", con = 0.9)
# The old behavior of cna() can be obtained by setting the argument asf.selection
# to its non-default value "none".
cna(ct1, outcome = "Y", con = 0.9, asf.selection = "none")
# Analysis of fuzzy-set data from Aleman (2009).
cna(d.pacts, con = .9, cov = .85)
cna(d.pacts, con = .9, cov = .85, asf.selection = "none")
# In the default setting, cna() does not return any model for d.pacts because
# the outcome takes a value >0.5 in every single case, meaning it does not change
# between presence and absence. No difference-making model should be inferred from
# such data.
# The implications of asf.selection can also be traced by
# the verbose argument:
cna(d.pacts, con = .9, cov = .85, verbose = TRUE)