robscale provides 11 exported functions spanning the full
robustness–efficiency spectrum: the bias-corrected standard deviation
(sd_c4, 100% ARE), the Gini mean difference (gmd, 98% ARE, 29.3%
breakdown), the average deviation from the median (adm, 88.3% ARE),
the Rousseeuw–Croux estimators (qn, 82.3% ARE, sn, 58.2% ARE, both
50% breakdown), the M-estimators (robScale, robLoc), and the
computationally light iqr_scaled and mad_scaled. The unified
scale_robust() dispatcher combines all 7 scale estimators in a
variance-weighted bootstrap ensemble for small samples (get_consistency_constant()
exposes the finite-sample bias-correction factors used throughout.
Against revss, robscale achieves 3.7–4.5x speedups for
robScale() and 4.0–4.3x for robLoc() at small adm() at robustbase, qn and
sn run at 1.8–6.0x and 2.1–8.9x respectively, peaking near
8.9x at gmd, iqr_scaled,
and mad_scaled beat their base R counterparts by 2.7–21.9x,
2.8–37.3x, and 4.1–26.1x respectively.
Speed comes from C++17 kernels with platform-specific SIMD
vectorization,
install.packages("robscale")
# Development version:
# install.packages("remotes")
# remotes::install_github("davdittrich/robscale")library(robscale)
x <- c(2.0, 3.1, 2.7, 2.9, 3.3) # clean measurements
# Recommended entry point: scale_robust()
scale_robust(x) # ensemble (small n < 20)
scale_robust(rnorm(50)) # auto-switches to gmd (n >= 20)
# Individual estimators span the robustness-efficiency frontier
gmd(x) # 98% ARE, 29.3% breakdown
qn(x) # 82.3% ARE, 50% breakdown
mad_scaled(x) # 36.8% ARE, 50% breakdown
# Confidence intervals --- analytical (default) or bootstrap
qn(x, ci = TRUE) # analytical 95% CI
scale_robust(x, method = "qn", ci = TRUE, boot_method = "bca") # BCa bootstrap CI
gmd(x, ci = TRUE, level = 0.99) # 99% analytical CI
# Outlier resistance
x[5] <- 100 # recording error
sd(x) # destroyed
gmd(x) # stable (29.3% breakdown)
qn(x) # stable (50% breakdown)
mad_scaled(x) # stable (50% breakdown)Table 1
Table 1: Scale estimators (sorted by decreasing ARE)
| Function | Purpose | ARE | Breakdown | Complexity | Reference |
|---|---|---|---|---|---|
sd_c4(x) |
Bias-corrected standard deviation | 100% | 0% | Welford (1962) | |
gmd(x) |
Gini mean difference | 98% | 29.3% | Gini (1912); Nair (1936) | |
adm(x) |
Average deviation from median | 88.3% | Nair (1947) | ||
qn(x) |
|
82.3% | 50% | Rousseeuw & Croux (1993) | |
sn(x) |
|
58.2% | 50% | Rousseeuw & Croux (1993) | |
robScale(x) |
M-estimate of scale | 55.0% | 50% |
|
Rousseeuw & Verboven (2002) |
iqr_scaled(x) |
Scaled interquartile range | 37% | 25% | Bickel & Lehmann (1976) | |
mad_scaled(x) |
Scaled median absolute deviation | 36.8% | 50% | Rousseeuw & Croux (1993) |
ARE values are asymptotic under normality. The code constants used for
analytical CIs round to two decimal places (e.g., 0.82 for
At the top of this spectrum, sd_c4 retains full efficiency but
collapses under a single outlier. The gmd occupies the practical sweet
spot: 98% efficiency with 29.3% breakdown—sufficient for most
contamination levels. For adversarial settings where breakdown must be
maximized, qn provides the best combination of high breakdown (50%)
and high efficiency (82.3%).
Table 2
Table 2: Dispatcher and utilities
| Function | Purpose |
|---|---|
scale_robust(x) |
Unified dispatcher: ensemble for small |
get_consistency_constant(method, n) |
Returns the consistency constant or finite-sample correction for a given estimator |
Additionally, robLoc(x) provides an M-estimate of location (98.4% ARE,
50% breakdown; Rousseeuw & Verboven 2002). All functions accept na.rm
(default FALSE). Most scale estimators accept ci = FALSE and
level = 0.95; when ci = TRUE, they return an object of class
"robscale_ci" containing the point estimate and a confidence interval
(analytical for individual estimators, bootstrap for scale_robust()).
The exception is robLoc(), which does not support confidence
intervals.
Computes the sample standard deviation corrected by
where
sd_c4(c(1, 2, 3, 5, 7, 8))Computes the Gini mean difference (Gini 1912), scaled by a consistency constant for asymptotic normality under the Gaussian model:
where
The GMD achieves 98% ARE (Nair 1936) with a 29.3% breakdown
point, making it the most statistically efficient robust alternative
in this package. It is the estimator scale_robust() auto-switches to
for large samples.
gmd(c(1, 2, 3, 5, 7, 8))
gmd(c(1, 2, 3, 5, 7, 8), constant = 1) # raw (unscaled)Computes the mean absolute deviation from the median, scaled by a consistency constant for asymptotic normality under the Gaussian model:
where center is
supplied, it replaces the median. The ADM achieves 88.3% ARE but
breaks down at a single outlier (
adm(c(1, 2, 3, 5, 7, 8))
adm(c(1, 2, 3, 5, 7, 8), constant = 1) # without consistency correction
adm(c(1, 2, 3, 5, 7, 8), ci = TRUE) # with 95% CIM-estimator for location defined by the logistic psi function (Rousseeuw
and Verboven 2002, Eq. 21), solved via Newton–Raphson iteration.
Starting value: scale).
Fallback logic: When scale is unknown and scale
is known and median(x) without
iteration. Providing a known scale lowers the minimum sample size from
4 to 3 because the MAD (which is unreliable at
robLoc(c(1, 2, 3, 5, 7, 8))
robLoc(c(1, 2, 3), scale = 1.5) # known scale enables n = 3robScale(x, loc = NULL, fallback = c("adm", "na"), implbound = 1e-4, na.rm = FALSE, maxit = 80L, tol = sqrt(.Machine$double.eps), ci = FALSE, level = 0.95)
M-estimator for scale solved by Newton–Raphson iteration on the M-scale
estimating equation
where tol, typically 3–4 iterations.
Degenerate input handling: When the sample size falls below the
minimum for iteration (4 for unknown location, 3 for known), the
function returns the initial MAD-based scale directly if it is nonzero.
When the MAD collapses to zero (i.e. MAD implbound), the
fallback argument controls the result:
fallback = "adm"(Default): returnsadm(x), maintaining a finite robust estimate where standard scale measures fail.fallback = "na": returnsNA, strictly matching the behavioral profile of therevsspackage.
Providing a known loc centers the data at that value and uses the
median-distance-to-zero ($(1.4826 \cdot \text{median}(|x_i - \mu|))$) as
the initial scale, lowering the minimum sample size from 4 to 3.
robScale(c(1, 2, 3, 5, 7, 8))
robScale(c(5, 5, 5, 5, 6), fallback = "na") # returns NA (revss compatibility)Computes the robscale implements qn_exact_threshold)
and a cache-aware parallelized Johnson-style algorithm for larger
samples.
qn(c(1, 2, 3, 5, 7, 8))
qn(c(1, 2, 3, 5, 7, 8), ci = TRUE) # with 95% CIComputes the robscale uses branchless sorting networks for
sn(c(1, 2, 3, 5, 7, 8))
sn(c(1, 2, 3, 5, 7, 8), ci = TRUE) # with 95% CIComputes the interquartile range scaled by a consistency constant for asymptotic normality under the Gaussian model:
where stats::IQR(), which requires a full
iqr_scaled(c(1, 2, 3, 5, 7, 8))
iqr_scaled(c(1, 2, 3, 5, 7, 8), constant = 1) # raw IQRComputes the median absolute deviation from the median, scaled by a consistency constant for asymptotic normality:
where stats::mad(), this
implementation uses adaptive
mad_scaled(c(1, 2, 3, 5, 7, 8))
mad_scaled(c(1, 2, 3, 5, 7, 8), constant = 1) # raw MADscale_robust(x, method = c("ensemble", "gmd", "sd", "mad", "iqr", "sn", "qn", "robScale"), auto_switch = TRUE, threshold = 20L, n_boot = 200L, na.rm = FALSE, ci = FALSE, level = 0.95, boot_method = c("auto", "analytical", "bca", "percentile", "parametric"))
Unified dispatcher for robust scale estimation. Operates in three modes:
-
Ensemble (
method = "ensemble",$n <$ threshold): variance-weighted combination of all 7 scale estimators via bootstrap resampling. -
Auto-switched GMD (
method = "ensemble",auto_switch = TRUE,$n \ge$ threshold): returnsgmd(x)directly. Named methods (e.g.method = "qn") are never intercepted byauto_switch—they always dispatch their own estimator regardless of$n$ . - Explicit method: dispatches to a specific estimator by name.
When ci = TRUE: the ensemble returns a robscale_ensemble_ci object
with a bootstrap CI (boot_method = "auto" selects BCa for boot_method = "auto" or "analytical" returns an analytical interval
(chi-squared for "sd", ARE-based normal approximation for all others);
boot_method = "bca", "percentile", or "parametric" returns a
bootstrap CI via n_boot resamples. "analytical" is not supported for
method = "ensemble".
scale_robust(c(1, 2, 3, 5, 7, 8)) # ensemble (n < 20)
scale_robust(rnorm(50)) # auto-switches to gmd (n >= 20)
scale_robust(rnorm(50), auto_switch = FALSE) # forces ensemble at any n
scale_robust(rnorm(50), method = "qn") # explicit Qn (not intercepted by auto_switch)
scale_robust(c(1, 2, 3, 5, 7, 8), ci = TRUE) # ensemble + bootstrap CI
scale_robust(rnorm(50), method = "qn", ci = TRUE) # Qn + analytical CI (default)
scale_robust(rnorm(50), method = "qn", ci = TRUE,
boot_method = "bca") # Qn + BCa bootstrap CIflowchart TD
A["scale_robust(x, method, auto_switch, threshold,\nn_boot, ci, boot_method)"] --> B{n < 2?}
B -- Yes --> C([Return NA])
B -- No --> D{"method='ensemble' AND\nauto_switch AND n >= threshold?"}
D -- Yes --> E["gmd() direct"]
E --> ECI{ci?}
ECI -- No --> EC([Return scalar])
ECI -- Yes --> ECA([Return robscale_ci, analytical])
D -- No --> F{method?}
F -- ensemble --> G["Bootstrap n_boot resamples"]
G --> H["Compute all 7 estimators per resample"]
H --> I["Inverse-variance weights from bootstrap variances"]
I --> J["Weighted sum on original data"]
J --> KCI{ci?}
KCI -- No --> K([Return scalar])
KCI -- Yes --> KA([Return robscale_ensemble_ci, bootstrap])
F -- "gmd/sd/mad/iqr/sn/qn/robScale" --> L["Compute estimator"]
L --> MCI{ci?}
MCI -- No --> MN([Return scalar])
MCI -- "Yes, auto/analytical" --> MA([Return robscale_ci, analytical])
MCI -- "Yes, bca/percentile/parametric" --> MB([Return robscale_ci, bootstrap])
The ensemble combines: sd_c4, gmd, mad_scaled, iqr_scaled, sn,
qn, and robScale. Bootstrap resampling uses a deterministic
XorShift32 PRNG (Marsaglia 2003) seeded deterministically from the
replicate index, ensuring reproducible results without requiring
set.seed().
Note: the method name "sd" maps to sd_c4.
Returns the consistency constant (or finite-sample correction factor)
used to make a given estimator consistent for the population standard
deviation under normality. Supported method values: "c4", "gmd",
"mad", "iqr", "sn", "qn".
When n = NULL, the function returns the asymptotic consistency
constant. When n is supplied, it returns the finite-sample correction
factor for that sample size—useful for small-sample bias (for
get_consistency_constant("mad") # asymptotic: 1/qnorm(3/4)
get_consistency_constant("qn", n = 10) # finite-sample correction at n = 10robscale achieves its speed gains through six cooperating mechanisms.
SIMD vectorization. The logistic psi function reduces to
vvtanh) on macOS; glibc libmvec on Linux x86_64
using the 4-wide AVX2 kernel (_ZGVdN4v_tanh); SLEEF as a fallback when
libmvec is absent; and #pragma omp simd as a portable fallback. The
Gini mean difference weighted sum is vectorized separately via an AVX2
FMA kernel (_mm256_fmadd_pd) for robLoc(), a fused
AVX2 kernel accumulates
-O2). Each estimator
chooses between Floyd–Rivest and pdqselect based on a runtime crossover
threshold derived from the per-core L2 cache size, minimizing cache
pressure for the specific working-set size of that estimator.
Stack-allocated memory arenas. A 128-double micro-buffer (1 KB)
covers the smallest samples (robScale/robLoc). For robScale uses one 2,048-double array (16 KB);
robLoc uses one 4,096-double array (32 KB, split into equal-sized
buffer and deviation halves). mad_scaled() and robScale() use fused
single-buffer algorithms that compute median and absolute deviations
in-place on the same array, reducing cache pressure in the ensemble
where multiple estimators share working memory.
Iteration convergence. Both M-estimators use Newton–Raphson
iteration (quadratic convergence, 2–4 iterations), replacing the scoring
fixed-point method (~6–8 iterations). For robLoc, robScale, a fused single-pass kernel computes
constexpr, replacing a division with
multiplication.
Parallelism and radix sorting. The cpp_scale_ensemble evaluates all boost::spreadsort::float_sort
(radix sort,
Numerical stability and build. sd_c4 uses Welford’s one-pass
algorithm for numerically stable variance computation. Sorting-network
entry points are instantiated once in src/sort_net_inst.cpp and
suppressed elsewhere via extern template, reducing a cold 12-core
build from approximately 300 s to 52 s.
robscale uses a tiered dispatch architecture to select the optimal
algorithm based on sample size and available hardware. The diagram below
shows how scale_robust() routes through the estimator hierarchy and
how each estimator selects its algorithm tier at runtime.
graph TD
SR["scale_robust() dispatcher"] --> ENS{method?}
ENS -- "ensemble, n < threshold<br/>or auto_switch=FALSE" --> BOOT["Bootstrap ensemble kernel<br/>(7 estimators × n_boot resamples)"]
ENS -- "ensemble, auto_switch=TRUE,<br/>n >= threshold" --> GMD_FAST["gmd() direct"]
ENS -- "gmd/sd/mad/iqr/sn/qn/robScale" --> SINGLE["Single estimator dispatch"]
subgraph "Scale Estimators"
SD["sd_c4"]
GMD["gmd"]
ADM["adm"]
QN["qn"]
SN["sn"]
RS["robScale"]
IQR["iqr_scaled"]
MAD["mad_scaled"]
end
subgraph "Location Estimators"
RL["robLoc"]
end
BOOT --> SD & GMD & MAD & IQR & SN & QN & RS
SINGLE --> SD & GMD & QN & SN & RS & IQR & MAD
GMD_FAST --> GMD
subgraph "Algorithm Tiers"
T1["n <= 56: Sorting networks\n(SIMD sel for n=8,16,32;\nscalar sel for n<=36)"]
T2["57 <= n < L2 threshold: Optimized scalar C++"]
T3["n >= L2 threshold: Parallel TBB kernels"]
T4["Adaptive selection dispatch\n(pdqselect or Floyd-Rivest\nper runtime L2 threshold)"]
end
QN & SN --> T1 & T2 & T3
IQR & MAD & RS --> T4
subgraph "Hardware Acceleration"
G2["AVX2 (4-wide tanh, robLoc fused kernel, GMD FMA)"]
H[Apple Accelerate]
I["glibc libmvec / SLEEF (tanh backend)"]
end
T1 & T2 & T3 --> G2 & H & I
Figures 1 and 2 show speedup factors relative to reference
implementations (Figure 1) and absolute wall-clock run times (Figure 2)
across sample sizes on a AMD Ryzen 9 5900HX with Radeon Graphics (Arch
Linux, R version 4.5.3 (2026-03-11), build flags:
-march=native -mtune=native -O2 -fno-math-errno -pipe -fPIC -fopenmp-simd -DROBSCALE_HAS_OMP_SIMD -I/usr/include -DROBSCALE_HAS_SLEEF -DROBSCALE_HAS_SYSTEM_TBB -I/usr/include -DROBSCALE_HAS_GLIBC_MVEC,
tanh backend: glibc libmvec (_ZGVdN4v_tanh), TBB: system oneTBB
(.so), benchmarked 2026-03-30). Baseline packages: robustbase 0.99.7
(Maechler et al. 2026), revss 3.1.0 (Adler 2020), Hmisc 5.2.5
(Harrell 2026), GiniDistance 0.1.1 (Nguyen and Dang 2022), collapse
2.1.6 (Krantz 2025).
Figure 1: Median speedup factor (x) vs. sample size robLoc, robScale, and adm against revss; Panel B
compares qn and sn against robustbase; Panel C compares gmd,
iqr_scaled, and mad_scaled against existing R implementations. The
thin grey line at
Figure 2: Median absolute run time for each robscale estimator across
sample sizes (log–log scale). All estimators are measured on the same
machine under identical conditions; the spread of lines reflects
algorithmic complexity (
robScale() and robLoc() reach 3.7–4.5x and 4.0–4.3x over
revss in the small-sample regime (adm() matches revss at small .Call() boundary) and leads by 1.6–7.0x
at revss interpreter overhead scales with iteration count, not just
vector length.
Table 3
robustbase::Qn |
robscale::qn |
Speedup | |
|---|---|---|---|
| 8 | 9.8 µs | 1.6 µs | 6.0x |
| 16 | 10.6 µs | 1.8 µs | 6.0x |
| 64 | 14.5 µs | 5.2 µs | 2.8x |
| 1024 | 451.9 µs | 220.1 µs | 2.0x |
| 65536 | 45969.5 µs | 10690.5 µs | 4.4x |
| 10000000 | 10.2 s | 2.1 s | 5.0x |
Table 4
robustbase::Sn |
robscale::sn |
Speedup | |
|---|---|---|---|
| 8 | 4.4 µs | 1.6 µs | 2.7x |
| 16 | 4.9 µs | 1.7 µs | 2.9x |
| 64 | 6.1 µs | 2.2 µs | 2.8x |
| 1024 | 35.7 µs | 17.3 µs | 2.1x |
| 65536 | 6893.7 µs | 935.8 µs | 7.4x |
| 10000000 | 1.5 s | 0.2 s | 8.4x |
For small to medium robscale leads by 1.8–6.0x for qn and
2.1–8.9x for sn, primarily from eliminating R dispatch overhead
and using stack memory. At qn runs in 2.1 s vs. 10.2 s
(5.0x) and sn in 0.2 s vs. 1.5 s (8.4x), as TBB parallelism
scales across cores.
Table 5
| Comparison | Speedup | |
|---|---|---|
| 64 | gmd vs GiniDistance | 13.4x |
| 64 | gmd vs Hmisc | 20.1x |
| 64 | iqr_scaled vs collapse | 4.6x |
| 64 | iqr_scaled vs stats | 30.2x |
| 64 | mad_scaled vs collapse | 5.3x |
| 64 | mad_scaled vs stats | 21.7x |
| 1024 | gmd vs GiniDistance | 3.6x |
| 1024 | gmd vs Hmisc | 5.2x |
| 1024 | iqr_scaled vs collapse | 2.5x |
| 1024 | iqr_scaled vs stats | 13.0x |
| 1024 | mad_scaled vs collapse | 1.8x |
| 1024 | mad_scaled vs stats | 6.3x |
| 65536 | gmd vs GiniDistance | 3.0x |
| 65536 | gmd vs Hmisc | 3.8x |
| 65536 | iqr_scaled vs collapse | 4.4x |
| 65536 | iqr_scaled vs stats | 5.8x |
| 65536 | mad_scaled vs collapse | 5.4x |
| 65536 | mad_scaled vs stats | 7.3x |
| 10000000 | gmd vs GiniDistance | 4.1x |
| 10000000 | gmd vs Hmisc | 5.6x |
| 10000000 | iqr_scaled vs collapse | 2.4x |
| 10000000 | iqr_scaled vs stats | 2.8x |
| 10000000 | mad_scaled vs collapse | 3.6x |
| 10000000 | mad_scaled vs stats | 4.7x |
gmd beats Hmisc::GiniMd by 2.7–21.9x (C++ vs. pure R) and
GiniDistance::gmd by 2.2–14.6x (both compiled, with robscale’s
edge from sorting networks). iqr_scaled leads stats::IQR by
2.8–37.3x (dual collapse::fquantile by 1.4–5.5x. mad_scaled leads stats::mad
by 4.1–26.1x and a collapse::fmedian-based MAD by 1.1–6.4x
(adaptive
[!NOTE] Source builds recommended. Installing from source (
install.packages("robscale", type = "source")) enables theconfigurescript to detect SIMD capabilities (AVX2/FMA on x86_64, NEON on ARM64) and link platform-specific libraries (Apple Accelerate, glibc libmvec, SLEEF). Pre-built CRAN binaries use portable settings and may not include these optimizations. Parallelism thresholds are derived from the detected per-core L2 cache size at runtime on all platforms. For maximum performance, add the following to~/.R/Makevarsbefore installing:CXXFLAGS = -O2 -march=native -mtune=native
The test suite verifies robscale against reference implementations:
M-estimator cross-check (tests/testthat/test-cross-check.R): For
adm, 1,800 randomly generated inputs (robLoc and robScale,
comparisons against revss revss
robscale follows the Rousseeuw and Verboven (2002)
estimating equations and constants but solves them via Newton–Raphson.
Other estimators:
-
gmd: exact match with the R formula$C \cdot 2/(n(n-1)) \sum (2i - n - 1) x_{(i)}$ (test-gmd.R) -
iqr_scaled: matchesIQR(x) * 0.741301109252801(test-iqr.R) -
mad_scaled: matchesstats::mad(x)(test-mad-scaled.R) -
sd_c4: matchessd(x) / c4(n)(test-sd-c4.R) -
scale_robustensemble: deterministic via fixed XorShift32 seeds (test-ensemble.R,test-scale-robust.R)
The Newton–Raphson iteration converges to the same fixed point as the scoring iteration—it solves the same estimating equation—so results differ only by rounding at the level of the convergence tolerance.
Full mathematical derivations, key constants, and algorithmic proofs are
in vignette("robscale-intro").
This package re-implements the M-estimators from the ‘revss’ package
(Adler 2020) and the
The API for the M-estimators is intentionally identical to revss:
adm(), robLoc(), and robScale() accept the same arguments and
return the same values. Code that uses revss can switch to robscale
by changing only the library() call.
For qn() and sn(), the function signatures match robustbase::Qn()
and robustbase::Sn() (with lowercase names for consistency).
Benchmark comparisons apply Fisher-consistency scaling where needed:
gmd() is compared against Hmisc::GiniMd(x) * 0.8862 and
GiniDistance::gmd(x) * 0.8862; iqr_scaled() against
stats::IQR(x) * 0.7413 and scaled collapse::fquantile() arrays; and
mad_scaled() directly against stats::mad() and a
collapse::fmedian() equivalent, since stats::mad() already applies
the 1.4826 factor.
Users who do not need compiled performance—or who prefer a
dependency-free pure-R package—should use revss or robustbase
directly. Both are mature, well-tested, and widely available.
Dennis Alexis Valin Dittrich (ORCID)
MIT. Copyright 2026 Dennis Alexis Valin Dittrich.
Adler, A. 2020. Revss: Robust Estimation in Very Small Samples. https://doi.org/10.32614/CRAN.package.revss.
Bickel, P. J., and E. L. Lehmann. 1976. “Descriptive Statistics for Nonparametric Models III. Dispersion.” Annals of Statistics 4 (6): 1139–58. https://doi.org/10.1214/aos/1176343648.
Gini, C. 1912. Variabilità e Mutabilità. Tipografia di Paolo Cuppini.
Harrell, Frank E., Jr. 2026. Hmisc: Harrell Miscellaneous. https://doi.org/10.32614/CRAN.package.Hmisc.
Krantz, Sebastian. 2025. Collapse: Advanced and Fast Data Transformation in R. https://doi.org/10.5281/zenodo.8433090.
Maechler, Martin, Peter Rousseeuw, Christophe Croux, et al. 2026. Robustbase: Basic Robust Statistics. https://CRAN.R-project.org/package=robustbase.
Marsaglia, George. 2003. “Xorshift RNGs.” Journal of Statistical Software 8 (14): 1–6. https://doi.org/10.18637/jss.v008.i14.
Nair, K. R. 1936. “On the Mean Deviation.” Biometrika 28 (3/4): 428–36. https://doi.org/10.2307/2333958.
Nair, K. R. 1947. “A Note on the Mean Deviation from the Median.” Biometrika 34 (3/4): 360–62. https://doi.org/10.2307/2332448.
Nguyen, Dang, and Xin Dang. 2022. GiniDistance: A New Gini Correlation Between Quantitative and Qualitative Variables. https://doi.org/10.32614/CRAN.package.GiniDistance.
Rousseeuw, P. J., and C. Croux. 1993. “Alternatives to the Median Absolute Deviation.” Journal of the American Statistical Association 88: 1273–83. https://doi.org/10.1080/01621459.1993.10476408.
Rousseeuw, P. J., and S. Verboven. 2002. “Robust Estimation in Very Small Samples.” Computational Statistics & Data Analysis 40 (4): 741–58. https://doi.org/10.1016/S0167-9473(02)00078-6.

