Learn R Programming

matrixCorr (version 0.12.3)

robust_dcor: Robust Distance Correlation

Description

Computes robust distance correlations by applying the biloop transformation to each numeric variable and then computing a U-centred robust distance-correlation statistic on the transformed variables.

Usage

robust_dcor(
  data,
  na_method = c("error", "pairwise", "complete"),
  p_value = FALSE,
  inference = c("none", "permutation"),
  n_perm = 999L,
  seed = NULL,
  c_const = 4,
  n_threads = getOption("matrixCorr.threads", 1L),
  output = c("matrix", "sparse", "edge_list"),
  threshold = 0,
  diag = TRUE,
  ...
)

# S3 method for robust_dcor print( x, digits = 4, n = NULL, topn = NULL, max_vars = NULL, width = NULL, show_ci = NULL, ... )

# S3 method for robust_dcor summary(object, topn = NULL, show_ci = NULL, ...)

# S3 method for robust_dcor plot( x, title = NULL, low_color = "indianred1", high_color = "steelblue1", mid_color = "white", value_text_size = 4, ci_text_size = 3, show_value = TRUE, ... )

Value

A symmetric correlation result. Dense output inherits from robust_dcor, corr_matrix, and matrix. Sparse and edge-list outputs use the package-standard corr_sparse and corr_edge_list representations.

Arguments

data

A numeric matrix or a data frame with at least two numeric columns. All non-numeric columns are dropped. Columns must be numeric.

na_method

Character scalar controlling missing-data handling. "error" rejects missing, NaN, and infinite values. "pairwise" recomputes each association on its own pairwise complete-case overlap. This is permissive, but different matrix entries may be based on different rows. "complete" performs listwise deletion once across the retained numeric columns and then computes the estimator on the common complete sample.

p_value

Logical (default FALSE). If TRUE, attach permutation p-values for pairwise independence.

inference

Character scalar. Use "none" (default) for estimates only or "permutation" to request permutation p-values. If inference = "permutation" is supplied with p_value = FALSE, p-values are inferred and returned.

n_perm

Positive integer; number of permutations used when p_value = TRUE. Default 999.

seed

Optional positive integer seed for permutation inference.

c_const

Positive numeric tuning constant for the biloop transformation. Default 4.

n_threads

Integer \(\geq 1\). Number of OpenMP threads. Defaults to getOption("matrixCorr.threads", 1L).

output

Output representation for the computed estimates: "matrix", "sparse", or "edge_list".

threshold

Non-negative absolute-value filter for non-matrix outputs. Must be 0 when output = "matrix".

diag

Logical; whether to include diagonal entries in "sparse" and "edge_list" outputs.

...

Deprecated compatibility aliases. Currently only check_na is supported.

x, object

An object of class robust_dcor.

digits

Integer; number of decimal places to print.

n

Optional row threshold for compact preview output.

topn

Optional number of leading/trailing rows to show when truncated.

max_vars

Optional maximum number of visible columns.

width

Optional display width.

show_ci

One of "yes" or "no".

title

Plot title.

low_color, high_color, mid_color

Colors used in the heatmap.

value_text_size, ci_text_size

Text sizes for plot labels.

show_value

Logical; overlay numeric values if TRUE.

Relationship to <code>dcor()</code>

robust_dcor() is not a replacement for dcor(). It estimates distance correlation after a bounded robust transformation. Large differences between dcor() and robust_dcor() can indicate that the classical dependence signal is driven by tail observations or outliers.

Author

Thiago de Paula Oliveira

Details

Permutation inference is computed for every unique column pair, so the workload grows as \(p(p-1)n_\mathrm{perm}/2\). A warning is emitted for large requests; reduce n_perm, reduce the number of columns, or run estimates without permutation p-values when this cost is not intended.

For each variable \(x = (x_1,\ldots,x_n)\), the wrapper first robustly standardises values using the median $$m_x = \mathrm{median}(x)$$ and raw median absolute deviation $$s_x = \mathrm{median}\{|x_i - m_x|\}.$$ If this scale is zero or non-finite, the implementation falls back to \(\mathrm{IQR}(x) / 1.34898\) and then the ordinary sample standard deviation. Columns with no positive finite fallback scale are treated as degenerate.

The standardised value \(z_i = (x_i - m_x) / s_x\) is mapped to two bounded coordinates by the biloop transformation $$\theta_i = 2\pi\tanh(z_i / c),$$ $$u_i = \begin{cases} c\{1-\cos(\theta_i)\}, & z_i > 0,\\ -c\{1-\cos(\theta_i)\}, & z_i < 0,\\ 0, & z_i = 0, \end{cases}$$ and $$v_i = \sin(\theta_i).$$ Pairwise distances are Euclidean distances in this transformed two-dimensional space, $$D^{(j)}_{ab} = \left[(u_{aj}-u_{bj})^2 + (v_{aj}-v_{bj})^2\right]^{1/2},\quad a \ne b,$$ with zero diagonal.

The transformed distance matrix is U-centred as $$A^{(j)}_{ab} = D^{(j)}_{ab} - \frac{r^{(j)}_a + r^{(j)}_b}{n - 2} + \frac{S^{(j)}}{(n - 1)(n - 2)},\quad a \ne b,$$ where \(r^{(j)}_a = \sum_{b \ne a}D^{(j)}_{ab}\) and \(S^{(j)} = \sum_{a \ne b}D^{(j)}_{ab}\). The diagonal of \(A^{(j)}\) is zero.

For variables \(j\) and \(k\), the U-centred robust squared distance covariance estimator is $$\widehat{\mathrm{dCov}}^2_u(j,k) = \frac{2}{n(n-3)}\sum_{a < b} A^{(j)}_{ab} A^{(k)}_{ab}.$$ The corresponding robust statistic is a non-negative clipped ratio based on this covariance estimator and the two transformed distance variances.

References

Leyder, J., Raymaekers, J., & Rousseeuw, P. J. (2025). Robust distance correlation through bounded transformations.

See Also

dcor(), bcdcor(), wincor(), pbcor(), skipped_corr()

Examples

Run this code
## Non-linear dependence: both estimators detect association.
set.seed(1)
n <- 200
x <- rnorm(n)
y <- x^2 + rnorm(n, sd = 0.2)

X <- cbind(x = x, y = y)

classical <- dcor(X)
robust <- robust_dcor(X)
round(c(
  dcor = classical["x", "y"],
  robust_dcor = robust["x", "y"]
), 3)

## One diagonal outlier can inflate classical dCor more than robust dCor.
set.seed(45)
x <- rnorm(20)
y <- rnorm(20)
x[1] <- 10
y[1] <- 10
X_out <- cbind(x = x, y = y)

classical <- dcor(X_out)
robust <- robust_dcor(X_out)
round(c(
  dcor = classical["x", "y"],
  robust_dcor = robust["x", "y"]
), 3)

print(classical)
print(robust)
summary(robust)
estimate(robust)
tidy(robust)
plot(robust)

## Several variables.
set.seed(7)
z <- rnorm(120)
X_multi <- cbind(
  linear = z + rnorm(120, sd = 0.3),
  nonlinear = z^2 + rnorm(120, sd = 0.3),
  noise = rnorm(120),
  outlier = rnorm(120)
)
X_multi[1, "outlier"] <- 12
X_multi[1, "noise"] <- 12

robust_multi <- robust_dcor(X_multi)

print(robust_multi)
summary(robust_multi)
plot(robust_multi)

Run the code above in your browser using DataLab