Run the PC (Peter-Clark) algorithm for causal discovery using one of several engines.
Usage
pc(engine = c("tetrad", "pcalg", "bnlearn"), test, alpha = 0.05, ...)Arguments
- engine
Character; which engine to use. Must be one of:
"tetrad"Tetrad Java library.
"pcalg"pcalg R package.
"bnlearn"bnlearn R package.
- test
Character; name of the conditional‐independence test.
- alpha
Numeric; significance level for the CI tests.
- ...
Additional arguments passed to the chosen engine (e.g. test or algorithm parameters).
Details
For specific details on the supported tests and parameters for each engine, see:
TetradSearch for Tetrad,
PcalgSearch for pcalg,
BnlearnSearch for bnlearn.
Recommendation
While it is possible to call the function returned directly with a data frame,
we recommend using disco(). This provides a consistent interface and handles knowledge
integration.
Value
A function that takes a single argument data (a data frame). When called,
this function returns a list containing:
knowledgeAKnowledgeobject with the background knowledge used in the causal discovery algorithm. Seeknowledge()for how to construct it.caugiAcaugi::caugiobject (of classPDAG) representing the learned causal graph from the causal discovery algorithm.
See also
Other causal discovery algorithms:
boss(),
boss_fci(),
fci(),
ges(),
gfci(),
grasp(),
grasp_fci(),
gs(),
iamb-family,
sp_fci(),
tfci(),
tges(),
tpc()
Examples
data(tpc_example)
#### Using pcalg engine ####
# Recommended path using disco()
pc_pcalg <- pc(engine = "pcalg", test = "fisher_z", alpha = 0.05)
disco(tpc_example, pc_pcalg)
#>
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: PDAG
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x1 --- child_x2
#> 2 child_x2 --> oldage_x5
#> 3 child_x2 --- youth_x4
#> 4 oldage_x5 --> oldage_x6
#> 5 youth_x3 --> oldage_x5
#> 6 youth_x4 --> oldage_x6
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
# or using pc_pcalg directly
pc_pcalg(tpc_example)
#>
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: PDAG
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x1 --- child_x2
#> 2 child_x2 --> oldage_x5
#> 3 child_x2 --- youth_x4
#> 4 oldage_x5 --> oldage_x6
#> 5 youth_x3 --> oldage_x5
#> 6 youth_x4 --> oldage_x6
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
# With all algorithm arguments specified
pc_pcalg <- pc(
engine = "pcalg",
test = "fisher_z",
alpha = 0.05,
fixedGaps = NULL,
fixedEdges = NULL,
NAdelete = FALSE,
m.max = 10,
u2pd = "relaxed",
skel.method = "original",
conservative = TRUE,
maj.rule = FALSE,
solve.confl = TRUE,
numCores = 1,
verbose = FALSE
)
#### Using bnlearn engine with required knowledge ####
kn <- knowledge(
tpc_example,
starts_with("child") %-->% starts_with("youth")
)
# Recommended path using disco()
pc_bnlearn <- pc(engine = "bnlearn", test = "fisher_z", alpha = 0.05)
disco(tpc_example, pc_bnlearn, knowledge = kn)
#> Warning: vstructure youth_x4 -> oldage_x6 <- oldage_x5 is not applicable, because one or both arcs are oriented in the opposite direction.
#>
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: PDAG
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x1 --- child_x2
#> 2 child_x1 --> youth_x3
#> 3 child_x1 --> youth_x4
#> 4 child_x2 --- oldage_x5
#> 5 child_x2 --> youth_x3
#> 6 child_x2 --> youth_x4
#> 7 oldage_x5 --- oldage_x6
#> 8 oldage_x5 --> youth_x3
#> 9 oldage_x6 --> youth_x4
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
#>
#> ── Variables ──
#>
#> var tier
#> <chr> <chr>
#> 1 child_x1 NA
#> 2 child_x2 NA
#> 3 oldage_x5 NA
#> 4 oldage_x6 NA
#> 5 youth_x3 NA
#> 6 youth_x4 NA
#> ── Edges ──
#>
#> ✔ child_x1 → youth_x3
#> ✔ child_x1 → youth_x4
#> ✔ child_x2 → youth_x3
#> ✔ child_x2 → youth_x4
# or using pc_bnlearn directly
pc_bnlearn <- pc_bnlearn |> set_knowledge(kn)
pc_bnlearn(tpc_example)
#> Warning: vstructure youth_x4 -> oldage_x6 <- oldage_x5 is not applicable, because one or both arcs are oriented in the opposite direction.
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: PDAG
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x1 --- child_x2
#> 2 child_x1 --> youth_x3
#> 3 child_x1 --> youth_x4
#> 4 child_x2 --- oldage_x5
#> 5 child_x2 --> youth_x3
#> 6 child_x2 --> youth_x4
#> 7 oldage_x5 --- oldage_x6
#> 8 oldage_x5 --> youth_x3
#> 9 oldage_x6 --> youth_x4
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
# With all algorithm arguments specified
pc_bnlearn <- pc(
engine = "bnlearn",
test = "fisher_z",
alpha = 0.05,
max.sx = 2,
debug = FALSE,
undirected = TRUE
)
disco(tpc_example, pc_bnlearn)
#>
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: PDAG
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x1 --- child_x2
#> 2 child_x2 --- oldage_x5
#> 3 child_x2 --- youth_x4
#> 4 oldage_x5 --- oldage_x6
#> 5 oldage_x5 --- youth_x3
#> 6 oldage_x6 --- youth_x4
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
#### Using tetrad engine with tier knowledge ####
# Requires Tetrad to be installed
if (verify_tetrad()$installed && verify_tetrad()$java_ok) {
kn <- knowledge(
tpc_example,
tier(
child ~ tidyselect::starts_with("child"),
youth ~ tidyselect::starts_with("youth"),
oldage ~ tidyselect::starts_with("oldage")
)
)
# Recommended path using disco()
pc_tetrad <- pc(engine = "tetrad", test = "fisher_z", alpha = 0.05)
disco(tpc_example, pc_tetrad, knowledge = kn)
# or using pc_tetrad directly
pc_tetrad <- pc_tetrad |> set_knowledge(kn)
pc_tetrad(tpc_example)
}
#>
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: UNKNOWN
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x2 --- child_x1
#> 2 child_x2 --> oldage_x5
#> 3 child_x2 --> youth_x4
#> 4 oldage_x5 --> oldage_x6
#> 5 youth_x3 --> oldage_x5
#> 6 youth_x4 --> oldage_x6
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
# With all algorithm arguments specified
if (verify_tetrad()$installed && verify_tetrad()$java_ok) {
pc_tetrad <- pc(
engine = "tetrad",
test = "fisher_z",
alpha = 0.05,
conflict_rule = 2,
depth = 10,
stable_fas = FALSE,
guarantee_cpdag = TRUE
)
disco(tpc_example, pc_tetrad)
}
#>
#> ── caugi graph ─────────────────────────────────────────────────────────────────
#> Graph class: PDAG
#>
#> ── Edges ──
#>
#> from edge to
#> <chr> <chr> <chr>
#> 1 child_x2 --- child_x1
#> 2 child_x2 --> oldage_x5
#> 3 child_x2 --- youth_x4
#> 4 oldage_x5 --> oldage_x6
#> 5 youth_x3 --> oldage_x5
#> 6 youth_x4 --> oldage_x6
#> ── Nodes ──
#>
#> name
#> <chr>
#> 1 child_x2
#> 2 child_x1
#> 3 youth_x4
#> 4 youth_x3
#> 5 oldage_x6
#> 6 oldage_x5
#> ── Knowledge object ────────────────────────────────────────────────────────────
