kernR kernR logo

Kernel-Based Causal Distributional Testing for R

kernR implements kernel-based hypothesis tests for causal inference and distributional treatment effects. It detects effects that standard methods (t-tests, linear regression, Double ML) miss entirely — including non-linear causal associations, variance shifts, and distributional changes that leave the mean unchanged.

Key Features

Related packages

dHSIC and energy test independence and differences between distributions without adjusting for confounders. DoubleML estimates an average treatment effect. kernR adds tests that adjust for confounders (bd-HSIC) and doubly robust tests of whether a treatment changes the whole outcome distribution (DR-DATE, DR-DETT), and a test for clustered data that permutes within clusters.

Installation

From GitHub (development version):

# install.packages("pak")
pak::pak("max578/kernR")

Pre-built binaries are available from r-universe (the PESTO cross-package dependency resolves automatically from the same registry):

install.packages("kernR", repos = c(
  "https://max578.r-universe.dev",
  "https://cloud.r-project.org"
))

CRAN submission is in preparation.

Quick Start

library(kernR)

# Detect non-linear dependence (HSIC)
set.seed(42)
x <- rnorm(200)
y <- x^2 + rnorm(200, sd = 0.3)  # quadratic relationship
cor.test(x, y)$p.value            # Pearson: p = 0.85 (misses it!)
hsic_test(x, y, seed = 1)        # HSIC:    p = 0.002 (detects it)

# Test for distributional treatment effect (DR-DATE)
n <- 300
covariates <- matrix(rnorm(n * 2), n, 2)
treatment  <- rbinom(n, 1, plogis(0.3 * covariates[, 1]))
outcome    <- treatment * rnorm(n, sd = 2) +       # treatment changes variance
              (1 - treatment) * rnorm(n, sd = 1) +  # but NOT the mean
              covariates[, 1]

t.test(outcome[treatment == 1], outcome[treatment == 0])  # p = 0.72 (blind)
dr_date_test(outcome, treatment, covariates, seed = 1)    # p = 0.002 (sees it)

When to Use kernR

Your question Traditional method kernR function Why kernR wins
Are X and Y related? (possibly non-linearly) cor.test() hsic_test() Detects U-shapes, periodicity, any non-linear pattern
Do two groups differ? (beyond means) t.test() mmd_test() Detects variance, shape, and tail differences
Does X causally affect Y? (with confounders) Double ML bd_hsic_test() Non-parametric; no functional form assumptions
Does treatment change the outcome distribution? t.test() / TMLE dr_date_test() Full distributional comparison; doubly robust
Effect on treated subgroup only? — dr_dett_test() One-sided overlap; robust in imperfect settings
Clustered/hierarchical data? Mixed models hierarchical_test() Non-parametric + proper permutation within clusters

Methodological Foundation

kernR implements methods from two peer-reviewed papers:

  1. Hu, R., Sejdinovic, D., & Evans, R. J. (2024). A kernel test for causal association via noise contrastive backdoor adjustment. Journal of Machine Learning Research, 25(160), 1–56. Paper | Original code

  2. Fawkes, J., Hu, R., Evans, R. J., & Sejdinovic, D. (2024). Doubly robust kernel statistics for testing distributional treatment effects. Transactions on Machine Learning Research. Paper | Original code

The hierarchical extension for nested/clustered data is a novel contribution of kernR.

Python Companion

A Python translation is available as kernP with an equivalent API built on NumPy/SciPy/scikit-learn.

Vignettes

Contributing

Bug reports and suggestions are welcome on the GitHub issue tracker. See CONTRIBUTING.md before opening a pull request.

Citation

If you use kernR in published work, please cite it:

citation("kernR")

Please also cite the papers listed under Methodological Foundation for the methods you use.

Licence

kernR is released under the MIT licence (sole copyright holder: Max Moldovan).

kernR has a hard dependency on PESTO, which is licensed under the GPL (>= 3). kernR's own source files are MIT-licensed, but because PESTO is required at run time, the installed combination of kernR and PESTO is a combined work and is therefore subject to the terms of the GPL (>= 3). Users who require a purely permissive (MIT-only) stack should be aware of this boundary.