A copula package integrated with `Distributions.jl`
The Copulas.jl package provides a large collection of models for dependence structures of real random vectors, known as copulas, with a wide selection of features:
- random number generation
- evaluation of (log)density and distribution functions
- copula-based multivariate distributions via Sklar's theorem
- fitting procedures, model diagnostics, and automatic family selection
- dependence metrics and tail coefficients
- marginalization, conditioning, and Rosenblatt transforms
- resampling-based hypothesis tests for dependence assumptions and goodness of fit
Since copulas are distribution functions, we integrate with the Distributions.jl API. This integration supports interoperability with other packages based on that API, such as Turing.jl. The precise 1.0 guarantees, including the treatment of singular and mixed measures, are defined on the Public API page.
Usually, users who work with copulas turn to the R package copula. While still well-maintained and regularly updated, the R package copula is a complicated code base in terms of readability, extensibility, reliability, and maintenance.
This package aims to provide a lightweight, fast, reliable, and maintainable copula implementation in native Julia. Core numerical paths are written generically where practical and model representations preserve their documented numeric types. Individual algorithms and external numerical backends may have narrower support; unsupported precision should fail explicitly rather than be silently narrowed. GPU and arbitrary-precision support are therefore operation- and backend-dependent rather than package-wide guarantees. See the Public API page for the normative numeric contract.
The package revolves around two main types:
Copula, the abstract supertype of all copulasSklarDist, the type for multivariate compound distributions via Sklar's theorem
The package is registered in Julia's General registry so you may simply install the package by running :
] add CopulasThe API contains random number generation, cdf and pdf evaluation, and the fit function from Distributions.jl. A typical use case might look like this:
using Copulas, Distributions, Random, Plots
X₁ = Gamma(2,3)
X₂ = Beta(1,4)
X₃ = Normal()
C = ClaytonCopula(3,5.2) # A 3-variate Clayton copula with θ = 5.2
D = SklarDist(C,(X₁,X₂,X₃)) # The final distribution
simu = rand(D,1000) # Generate a dataset
D̂ = fit(SklarDist{ClaytonCopula,Tuple{Gamma,Beta,Normal}}, simu) # estimate a model
plot(D̂) # plot the resultThe list of available copula models is very large; browse the Bestiary for definitions, parameterizations, constructors, and model-specific caveats. The general implementation philosophy is for the code to follow the mathematical boundaries of the implemented concepts. For example, this is the only implementation we know (in any language) that allows for all Archimedean copulas to be sampled: we use the Williamson transformation for non-standard generators, including user-provided black-box ones.
Other Julia packages cover related use cases. BivariateCopulas.jl focuses on a compact set of bivariate copulas, joint distributions, conditioning, and visualization. DatagenCopulaBased.jl focuses on data generation, including selected nested and chained constructions. The comparison below summarizes capabilities documented by each project; “Not documented” means that the linked public README does not advertise the feature, not that no implementation can exist.
| Capability | Copulas.jl |
DatagenCopulaBased.jl |
BivariateCopulas.jl |
|---|---|---|---|
| Sampling | ✅ Vector and matrix rand interface |
✅ Primary interface | |
Distributions.jl distribution API |
✅ | ❌ Not documented | |
| CDF and density | ✅ When defined by the model | ❌ Not documented as a common interface | |
| Copula plus arbitrary margins | ✅ SklarDist, any supported dimension |
||
| Parameter fitting | ✅ Quick fits and full CopulaModel results |
❌ Not documented | ❌ Not documented |
| Automatic family selection | ✅ Explicit candidate sets with AIC, BIC, AICc, or HQC | ❌ Not documented | ❌ Not documented |
| Statistical-model diagnostics | ✅ Covariance, confidence intervals, residuals, information criteria | ❌ Not documented | ❌ Not documented |
| Dependence measures | ✅ Scalar and pairwise rank and tail measures | ❌ Not documented as a common interface | |
| Subsetting and conditioning | ✅ Copulas and SklarDist; univariate or multivariate results |
❌ Not documented | |
| Rosenblatt and inverse Rosenblatt transforms | ✅ | ❌ Not documented | ❌ Not documented |
| Hypothesis tests | ✅ Independence, exchangeability, radial symmetry, extreme-value dependence, goodness of fit | ❌ Not documented | ❌ Not documented |
| Plot recipes | ✅ Pairwise samples, margins, CDF/PDF contours and surfaces | ❌ Not documented | |
| Archimedean models | ✅ Clayton, Frank, Gumbel, Joe, AMH, inverse Gaussian, BB1--BB10, and custom/empirical generators | ||
| Structured multivariate models | ✅ Liouville and nested Archimedean copulas | ✅ Same-family nested copulas and bivariate chains | ❌ Not documented |
| Elliptical models | ✅ Gaussian and Student, multivariate | ✅ Gaussian and Student | |
| Extreme-value models | ✅ Logistic, Galambos, Hüsler--Reiss, extremal-t, Tawn, asymmetric and spectral families; bivariate and multivariate |
❌ Not documented | |
| Nonparametric copulas | ✅ Empirical, beta, Bernstein, checkerboard, empirical EV | ❌ Not documented | ❌ Not documented |
| Archimax models | ❌ Not documented | ❌ Not documented |
The table compares public scope rather than runtime performance; algorithmic cost depends strongly on the family, dimension, and requested operation.
Here is a practical tour of the main public workflows. For precise behavioral guarantees see the Public API; for theory and model-specific guidance see the Manual and Bestiary.
You can construct a copula object with their respective constructors. They behave like multivariate distributions from Distributions.jl and respect their API:
using Copulas, Distributions, Random, StatsBase
# A 3-variate Clayton copula
C = ClaytonCopula(3, 2.0)
U = rand(C, 5)
Distributions.loglikelihood(C, U)To build multivariate distributions, you can compose a copula with marginals via Sklar’s theorem:
X₁, X₂, X₃ = Gamma(2,3), Beta(1,5), LogNormal(0,1)
C2 = GumbelCopula(3, 1.7)
D = SklarDist(C2, (X₁, X₂, X₃))
rand(D, 3)
pdf(D, rand(3))You can get scalar dependence metrics at copula level:
(
kendall_tau = Copulas.τ(C),
spearm_rho = Copulas.ρ(C),
blomqvist_beta = Copulas.β(C),
gini_gamma = Copulas.γ(C),
entropy_iota = Copulas.ι(C),
lower_tail_dep = Copulas.λₗ(C),
upper_tail_dep = Copulas.λᵤ(C)
)Pairwise matrices of bivariate versions are available through StatsBase.corkendall(C), StatsBase.corspearman(C), Copulas.corblomqvist(C), Copulas.corgini(C), Copulas.corentropy(C), Copulas.corlowertail(C), and Copulas.coruppertail(C).
Same functions work passing a dataset instead of the copula for their empirical counterpart.
The measure function measures hypercubes under the distribution of the copula. You can access the Rosenblatt transformation of a copula (or a Sklar distribution) through the rosenblatt and inverse_rosenblatt functions:
Copulas.measure(C, (0.1,0.2,0.3), (0.9,0.8,0.7))
x = rand(D, 100)
u = rosenblatt(D, x)
x2 = inverse_rosenblatt(D, u)
maximum(abs.(x2 .- x))You can subset the dimensions of a model through subsetdims(), and you can condition a model on some of its marginals with condition():
S23 = subsetdims(C2, (2,3))
StatsBase.corkendall(S23)
Dj = condition(C2, 2, 0.3) # Distributions of (U₁, U₃) | U₂ = 0.3 (d=2)
Distributions.cdf(Dj, [0.95, 0.80])
Dc = condition(D, (2,3), (0.3, 0.2))
rand(Dc, 2)Fit both marginals and copula from raw data (Sklar):
X = rand(D, 150)
M = fit(CopulaModel, SklarDist{GumbelCopula, Tuple{Gamma,Beta,LogNormal}}, X; copula_method=:mle)Directly fit a copula from pseudo-observations U:
U = pseudos(X)
Ĉ = fit(GumbelCopula, U; method=:itau)Notes
- Direct copula fits default to
method=:mle. Usemethod=:mpl, pseudo_values=falsefor maximum pseudo-likelihood from raw observations. - Sklar fits default to sequential
sklar_method=:ifm;:ecdfis the rank-based alternative. Neither route is joint full maximum likelihood. - Their copula step defaults to
copula_method=:mlewhen supported, otherwise to the family's advertised default; either can be replaced explicitly.
Use CopulaModel when diagnostics or later inference matter. It stores only
the fitted distribution, original data, fitted log-likelihood, and minimal
replay recipe; coefficients, transformed observations, parameter blocks, and
the independence likelihood are derived when requested. Estimation itself does
not compute uncertainty: apply infer(M; method=...) to obtain a separate
CopulaInference, then use vcov, stderror, and confint on that result.
For Sklar fits, bootstrap inference refits both the margins and the copula and
retains their complete covariance, including cross-component terms.
If the family is not known in advance, fit an explicit, scientifically appropriate candidate set and rank successful fits by an information criterion:
Msel = fit(
CopulaModel,
Copulas.Copula,
U;
candidates=(ClaytonCopula, GumbelCopula, FrankCopula),
criterion=:bic,
)
selection_table(Msel)
Mbest = selected_model(Msel)Selection returns a CopulaSelection, so its candidate report is not stored in
the winning CopulaModel. Selection is deliberately explicit: Copulas.jl does
not treat every available family as a sensible candidate for every dimension or scientific question. See
the fitting interface for post-fit inference,
confidence intervals, residuals, and selection caveats.
The test constructors share the StatsAPI.HypothesisTest interface and return a
CopulaTest queried with teststatistic, pvalue, and nobs. Available
procedures assess mutual independence, exchangeability, radial symmetry, the
extreme-value property, and goodness of fit to a specified fitted family.
test = IndependenceCopulaTest(U; N=19, rng=Xoshiro(42))
(statistic=teststatistic(test), pvalue=pvalue(test), observations=nobs(test))These are resampling-based procedures. Set an RNG for reproducibility, use a
larger N for scientific work, and check the assumptions—especially continuity
and absence of ties—on the hypothesis-testing page.
If you want to contribute to the package, ask a question, found a bug or simply want to chat, do not hesitate to open an issue on the Copulas.jl repository
Do not hesitate to star this repository to show support. If you use this package in your researches, please cite it with the following bibtex code:
@article{LavernyJimenez2024,
author = {Oskar Laverny and Santiago Jimenez},
title = {Copulas.jl: A fully Distributions.jl-compliant copula package},
journal = {Journal of Open Source Software},
doi = {10.21105/joss.06189},
url = {https://doi.org/10.21105/joss.06189},
year = {2024},
publisher = {The Open Journal},
volume = {9},
number = {94},
pages = {6189}
}