lingamr implements eleven causal discovery estimators.
They all share the same goal — recovering a directed causal structure
from observational data — but each relaxes a different assumption of the
basic LiNGAM model. This vignette helps you pick the right one.
The basic LiNGAM model assumes:
- Linear causal relationships,
- an acyclic causal graph (a DAG),
- non-Gaussian, mutually independent error terms,
- no latent confounder (every common cause is observed),
- i.i.d. observations (no time structure, no group structure),
- continuous variables and a complete (no
NA) data matrix.
When all six hold, use lingam_direct(). Every other
estimator in the package exists to relax one (or two) of these
assumptions.
Decision Guide
Work through the questions in order; the first “yes” points to the method.
-
Are the observations a time series?
- Yes, and temporal dependence is autoregressive →
VAR-LiNGAM (
lingam_var()) - Yes, and the VAR residuals stay autocorrelated even with more lags
(moving-average disturbances) → VARMA-LiNGAM
(
lingam_varma())
- Yes, and temporal dependence is autoregressive →
VAR-LiNGAM (
-
Are causal relationships plausibly nonlinear?
- Yes, and all major common causes are observed →
RESIT (
lingam_resit()) - Yes, and there may be unobserved variables → CAM-UV
(
lingam_camuv())
- Yes, and all major common causes are observed →
RESIT (
-
Might a latent confounder exist (linear case)?
- You want to know which part of the causal order is still
trustworthy → BottomUpParceLiNGAM
(
lingam_parce()) - You want to know which specific pairs are confounded →
RCD (
lingam_rcd())
- You want to know which part of the causal order is still
trustworthy → BottomUpParceLiNGAM
(
-
Does the data mix continuous and discrete
variables? → LiM (
lingam_lim(); binary by default, Poisson counts viais_poisson = TRUE) -
Do you have several datasets that share a causal
structure (multiple sites, periods, cohorts)? →
MultiGroup Direct LiNGAM
(
lingam_multi_group()) -
Does the data contain missing values
(
NA)? →bootstrap_with_imputation()(bootstrap + multiple imputation) -
Are there many variables (tens to hundreds), or even p >
n? → HighDimDirectLiNGAM
(
lingam_high_dim()) -
None of the above → Direct LiNGAM
(
lingam_direct())
If several complications apply at once (say, a nonlinear time series), no single estimator handles both; you will have to prioritize the violation that matters most for your data, or transform the data (e.g. differencing a non-stationary series) so that fewer assumptions are violated.
Method Overview
| Method | Function | Handles | Output notes | Bootstrap |
|---|---|---|---|---|
| Direct LiNGAM | lingam_direct() |
The baseline: linear, acyclic, non-Gaussian, i.i.d. | Causal order + coefficient matrix | lingam_direct_bootstrap() |
| HighDimDirectLiNGAM | lingam_high_dim() |
Many variables; p > n | Same object as lingam_direct()
|
— |
| VAR-LiNGAM | lingam_var() |
Stationary time series (AR) | Instantaneous B0 + lagged matrices | lingam_var_bootstrap() |
| VARMA-LiNGAM | lingam_varma() |
Time series with MA errors | AR (psi) + MA (omega) matrices | lingam_varma_bootstrap() |
| MultiGroup Direct LiNGAM | lingam_multi_group() |
Multiple datasets, one shared order | Common order + per-group matrices | lingam_multi_group_bootstrap() |
| BottomUpParceLiNGAM | lingam_parce() |
Latent confounders (linear) | Unresolved block; NA entries |
lingam_parce_bootstrap() |
| RCD | lingam_rcd() |
Latent confounders (linear) | Ancestor sets; confounded pairs NA
|
lingam_rcd_bootstrap() |
| RESIT | lingam_resit() |
Nonlinear additive noise | 0/1 edges (no coefficients) | lingam_resit_bootstrap() |
| CAM-UV | lingam_camuv() |
Nonlinear + unobserved variables | Parents list; UCP/UBP pairs NA
|
— |
| LiM | lingam_lim() |
Mixed continuous/discrete data | Coefficient matrix | — |
| Bootstrap with imputation | bootstrap_with_imputation() |
Missing values (NA) |
Aggregate via as_bootstrap_result()
|
(is itself a bootstrap) |
Two practical cost notes:
-
HSIC-based methods (ParceLiNGAM, RCD, RESIT,
CAM-UV, and
lingam_direct(measure = "kernel")) build Gram matrices per test; they are not recommended for in the thousands — subsample first. -
Direct LiNGAM costs
in the number of variables; for large
switch to
lingam_high_dim().
Worked examples for every method are on the package website:
When LiNGAM Cannot Be Used
When the assumptions are not met, estimation either fails or systematically recovers an incorrect structure.
| Assumption | When problems arise | Remedy / alternative |
|---|---|---|
| Non-Gaussian errors | When all errors follow a Gaussian distribution, the causal direction becomes unidentifiable | No LiNGAM variant can help; consider constraint-based methods
(e.g. the PC algorithm in pcalg), which return an
equivalence class instead of a unique direction |
| Acyclic graph (DAG) | When feedback loops (x -> y -> x) exist | Consider Cyclic LiNGAM (implemented in the Python
lingam package) |
| No latent common causes | When unobserved common causes (hidden confounders) exist |
lingam_parce(), lingam_rcd() (linear),
lingam_camuv() (nonlinear) |
| Linear causal relationships | When the relationships among variables are nonlinear |
lingam_resit(), lingam_camuv()
|
| No measurement error (upstream variables) | When heavy measurement error is present on variables near the root, the direction is systematically reversed | See the measurement error paradox in the Direct LiNGAM article |
| Independent and identically distributed (i.i.d.) | Time-series data, or data pooled across heterogeneous sources |
lingam_var() / lingam_varma() (time
series), lingam_multi_group() (grouped data) |
| Sufficient sample size | When is extremely small relative to the number of variables (rule of thumb: ), estimation tends to be unstable | Reduce the number of variables; sparsify with
reg_method = "adaptive_lasso"; for
use lingam_high_dim()
|
A Checklist to Verify in Advance
Before starting an actual analysis, we recommend confirming the following.
- Acyclicity of the graph – Can feedback loops be ruled out from domain expertise?
-
Absence of latent variables – Are the key observed
variables all present? If not, prefer
lingam_parce()/lingam_rcd()/lingam_camuv(). -
Non-Gaussianity of the errors – Can be checked with
test_residual_normality()(though this is a post-estimation diagnostic). As a quick check beforehand, visually inspect each variable’s histogram and skewness. - Presence of measurement error – Is there measurement error on variables near the root? If so, interpret with care.
- Sample size – Aim for . If it falls short, do not over-trust the results.
Summary: LiNGAM is powerful when all assumptions – linear, acyclic, non-Gaussian, no latent variables, and i.i.d. – hold, and
lingamrprovides a dedicated estimator for the most common way each assumption breaks. Verifying the assumptions with domain knowledge and residual diagnostics before analysis is the first step toward reliable causal inference.
