A fast, multi-language library for statistical conditional independence testing. The Rust core implements several well-known tests from the power-divergence family (for discrete data) and Pearson-correlation-based tests (for continuous data), with bindings for Python, R, and JavaScript.
| Test | Data type | Output |
|---|---|---|
chi_squared |
Discrete | (p_value, statistic, dof) |
cressie_read |
Discrete | (p_value, statistic, dof) |
freeman_tukey |
Discrete | (p_value, statistic, dof) |
log_likelihood |
Discrete | (p_value, statistic, dof) |
modified_likelihood |
Discrete | (p_value, statistic, dof) |
pearson_correlation |
Continuous | (p_value, coefficient) |
pearson_equivalence |
Continuous | (p_value, coefficient) |
All tests accept an optional conditioning matrix Z. Pass an empty matrix for unconditional tests. Every test can also run in boolean mode, returning only an independence verdict at a given significance level instead of the raw statistic.
ci-core Core test implementations and CITest trait (Rust library)
ci-python PyO3 bindings — importable as ci_python
cir extendr bindings — importable as an R package
ci-js wasm-pack bindings
Downstream crates depend only on ci-core. The bindings crates are thin wrappers that handle type conversion.
Documentation can be seen at: https://giphouse.github.io/Conditional-Independence-Testing/
Add ci_core to your Cargo.toml:
[dependencies]
ci_core = { git = "https://github.com/GiPHouse/Conditional-Independence-Testing" }Run a test:
use ci_core::ci_tests::chi_squared::ChiSquared;
use ci_core::strategy::{CITest, TestResult};
use ndarray::{Array1, Array2};
let test = ChiSquared::new(/*boolean=*/false, /*significance_level=*/0.05);
let x = Array1::from_vec(vec![0.0, 1.0, 0.0, 1.0, 0.0]);
let y = Array1::from_vec(vec![1.0, 0.0, 1.0, 0.0, 1.0]);
let z = Array2::zeros((0, 0)); // empty conditioning set
match test.run_test(x, y, z)? {
TestResult::Statistic(p_value, statistic, dof) => {
println!("p={p_value:.4}, χ²={statistic:.4}, df={dof}");
}
_ => unreachable!(),
}For conditional tests, pass a matrix where each column is one conditioning variable:
use ndarray::{Array2, Axis, stack};
// Condition on two variables z1 and z2
let z = stack(Axis(1), &[z1.view(), z2.view()])?;
test.run_test(x, y, z)?;Build and install the Python package from the repository root:
pip install maturin
maturin develop -m crates/ci-python/Cargo.tomlimport numpy as np
from ci_python import ChiSquared, PearsonCorrelation
test = ChiSquared(boolean=False, significance_level=0.05)
x = np.array([0.0, 1.0, 0.0, 1.0, 0.0])
y = np.array([1.0, 0.0, 1.0, 0.0, 1.0])
z = np.empty((len(x), 0)) # unconditional
p_value, statistic, dof = test.run_test(x, y, z)
print(f"p={p_value:.4f}, χ²={statistic:.4f}, df={dof}")For continuous data:
test = PearsonCorrelation(boolean=False, significance_level=0.05)
p_value, coefficient = test.run_test(x, y, z)Install the R package from the repository root:
# From within R, using devtools
devtools::install("crates/cir")library(cir)
x <- c(0, 1, 0, 1, 0)
y <- c(1, 0, 1, 0, 1)
z <- matrix(nrow = length(x), ncol = 0) # unconditional
result <- chi_squared_test(x, y, z, boolean = FALSE, significance_level = 0.05)
cat("p =", result$p_value, " statistic =", result$statistic, "\n")Boolean mode returns only an independence verdict:
result <- pearson_correlation_test(x, y, z, boolean = TRUE, significance_level = 0.05)
cat("independent:", result$independent, "\n")Install the JavaScript package from the repository root:
// For directly using it on the web
wasm-pack build --target web
// For using it in NodeJs
wasm-pack build --target nodejsimport init, { log_likelihood_test } from "../pkg/ci_js.js";
const wasm = await import("../pkg/ci_js.js");
beforeAll(async () => {
await wasm.default.init();
});
const x = toFloat64(1, 1, 2, 2, 1, 1, 2, 2);
const y = toFloat64(1, 2, 1, 2, 1, 2, 1, 2);
const z = new Float64Array(0);
const z_rows = 0;
const z_cols = 0;
const boolean = false;
const significance_level = 0.05;
const [p_value, statistic, dof] = log_likelihood_test(
z,
z_rows,
z_cols,
x,
y,
boolean,
significance_level,
);See CONTRIBUTING.md for setup instructions, coding standards, and how to add a new CI test.
Quick check before opening a PR:
cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspaceLicensed under the MIT license.