Performs the nonparametric two-sample or \(K\)-sample Ball Divergence test for equality of multivariate distributions
bd.test(x, ...)
# S3 method for default
bd.test(
x,
y = NULL,
num.permutations = 99,
method = c("permutation", "limit"),
distance = FALSE,
size = NULL,
seed = 1,
num.threads = 0,
kbd.type = c("sum", "maxsum", "max"),
weight = c("constant", "variance"),
...
)
# S3 method for formula
bd.test(formula, data, subset, na.action, ...)
a numeric vector, matrix, data.frame, or a list containing at least two numeric vectors, matrices, or data.frames.
further arguments to be passed to or from methods.
a numeric vector, matrix, data.frame.
the number of permutation replications. When num.permutations = 0
, the function just returns
the Ball Divergence statistic. Default: num.permutations = 99
.
if method = "permutation"
, a permutation procedure is carried out to compute the \(p\)-value;
if method = "limit"
, an approximate null distribution is used when weight = "constant"
.
Any unambiguous substring can be given. Default method = "permutation"
.
if distance = TRUE
, the elements of x
will be considered as a distance matrix. Default: distance = FALSE
.
a vector recording sample size of each group.
the random seed. Default seed = 1
.
number of threads. If num.threads = 0
, then all of available cores will be used. Default num.threads = 0
.
a character string specifying the \(K\)-sample Ball Divergence test statistic,
must be one of "sum"
, "summax"
, or "max"
. Any unambiguous substring can be given.
Default kbd.type = "sum"
.
a character string specifying the weight form of Ball Divergence statistic.
It must be one of "constant"
or "variance"
.
Any unambiguous substring can be given. Default: weight = "constant"
.
a formula of the form response ~ group
where response
gives the data values and group
a vector or factor of the corresponding groups.
an optional matrix or data frame (or similar: see model.frame
) containing the variables in the formula formula
. By default the variables are taken from environment(formula)
.
an optional vector specifying a subset of observations to be used.
a function which indicates what should happen when the data contain NA
s. Defaults to getOption("na.action")
.
If num.permutations > 0
, bd.test
returns a htest
class object containing the following components:
statistic
Ball Divergence statistic.
p.value
the \(p\)-value for the test.
replicates
permutation replications of the test statistic.
size
sample sizes.
complete.info
a list
mainly containing two vectors, the first vector is the Ball Divergence statistics
with different aggregation strategy and weight, the second vector is the \(p\)-values of tests.
alternative
a character string describing the alternative hypothesis.
method
a character string indicating what type of test was performed.
data.name
description of data.
If num.permutations = 0
, bd.test
returns a statistic value.
bd.test
is nonparametric test for the two-sample or \(K\)-sample problem.
It can detect distribution difference between \(K(K \geq 2)\) sample even though sample size are imbalanced.
This test can cope well multivariate dataset or complex dataset.
If only x
is given, the statistic is
computed from the original pooled samples, stacked in
matrix where each row is a multivariate observation, or from the distance matrix
when distance = TRUE
. The first sizes[1]
rows of x
are the first sample, the next
sizes[2]
rows of x
are the second sample, etc.
If x
is a list
, its elements are taken as the samples to be compared,
and hence, this list
must contain at least two numeric data vectors, matrices or data.frames.
bd.test
utilizes the Ball Divergence statistics (see bd
) to measure dispersion and
derives a \(p\)-value via replicating the random permutation num.permutations
times.
The function simply returns the test statistic
when num.permutations = 0
.
The time complexity of bd.test
is around \(O(R \times n^2)\),
where \(R\) = num.permutations
and \(n\) is sample size.
Actually, bd.test
simultaneously computing "sum"
, "summax"
, and "max"
Ball Divergence statistics
when \(K \geq 3\).
Users can get other Ball Divergence statistics and their corresponding \(p\)-values
in the complete.info
element of output. We give a quick example below to illustrate.
Wenliang Pan, Yuan Tian, Xueqin Wang, Heping Zhang. Ball Divergence: Nonparametric two sample test. Annals of Statistics. 46 (2018), no. 3, 1109--1137. doi:10.1214/17-AOS1579. https://projecteuclid.org/euclid.aos/1525313077
Jin Zhu, Wenliang Pan, Wei Zheng, and Xueqin Wang (2021). Ball: An R Package for Detecting Distribution Difference and Association in Metric Spaces, Journal of Statistical Software, Vol.97(6), doi: 10.18637/jss.v097.i06.
################# Quick Start #################
set.seed(1)
x <- rnorm(50)
y <- rnorm(50, mean = 1)
# plot(density(x))
# lines(density(y), col = "red")
bd.test(x = x, y = y)
#>
#> 2-sample Ball Divergence Test (Permutation)
#>
#> data: x and y
#> number of observations = 100, group sizes: 50 50
#> replicates = 99, weight: constant
#> bd.constant = 0.092215, p-value = 0.01
#> alternative hypothesis: distributions of samples are distinct
#>
################# Quick Start #################
x <- matrix(rnorm(100), nrow = 50, ncol = 2)
y <- matrix(rnorm(100, mean = 3), nrow = 50, ncol = 2)
# Hypothesis test with Standard Ball Divergence:
bd.test(x = x, y = y)
#>
#> 2-sample Ball Divergence Test (Permutation)
#>
#> data: x and y
#> number of observations = 100, group sizes: 50 50
#> replicates = 99, weight: constant
#> bd.constant = 0.54533, p-value = 0.01
#> alternative hypothesis: distributions of samples are distinct
#>
################# Simlated Non-Hilbert data #################
data("bdvmf")
if (FALSE) {
library(scatterplot3d)
scatterplot3d(bdvmf[["x"]], color = bdvmf[["group"]],
xlab = "X1", ylab = "X2", zlab = "X3")
}
# calculate geodesic distance between sample:
Dmat <- nhdist(bdvmf[["x"]], method = "geodesic")
# hypothesis test with BD :
bd.test(x = Dmat, size = c(150, 150), num.permutations = 99, distance = TRUE)
#>
#> 2-sample Ball Divergence Test (Permutation)
#>
#> data: Dmat
#> number of observations = 300, group sizes: 150 150
#> replicates = 99, weight: constant
#> bd.constant = 0.14483, p-value = 0.01
#> alternative hypothesis: distributions of samples are distinct
#>
################# Non-Hilbert Real Data #################
# load data:
data("macaques")
# number of femala and male Macaca fascicularis:
table(macaques[["group"]])
#>
#> f m
#> 9 9
# calculate Riemannian shape distance matrix:
Dmat <- nhdist(macaques[["x"]], method = "riemann")
# hypothesis test with BD:
bd.test(x = Dmat, num.permutations = 99, size = c(9, 9), distance = TRUE)
#>
#> 2-sample Ball Divergence Test (Permutation)
#>
#> data: Dmat
#> number of observations = 18, group sizes: 9 9
#> replicates = 99, weight: constant
#> bd.constant = 0.1922, p-value = 0.03
#> alternative hypothesis: distributions of samples are distinct
#>
################ K-sample Test #################
n <- 150
bd.test(rnorm(n), size = c(40, 50, 60))
#>
#> 3-sample Ball Divergence Test (Permutation)
#>
#> data: rnorm(n)
#> number of observations = 150, group sizes: 40 50 60
#> replicates = 99, weight: constant, kbd.type: sum
#> kbd.sum.constant = 0.031322, p-value = 0.58
#> alternative hypothesis: distributions of samples are distinct
#>
# alternative input method:
x <- lapply(c(40, 50, 60), rnorm)
res <- bd.test(x)
res
#>
#> 3-sample Ball Divergence Test (Permutation)
#>
#> data: x
#> number of observations = 150, group sizes: 40 50 60
#> replicates = 99, weight: constant, kbd.type: sum
#> kbd.sum.constant = 0.021076, p-value = 0.91
#> alternative hypothesis: distributions of samples are distinct
#>
## get all Ball Divergence statistics:
res[["complete.info"]][["statistic"]]
#> kbd.sum.constant kbd.sum.variance kbd.max.constant kbd.max.variance
#> 0.02107627 0.02107627 0.01503796 0.01503796
#> kbd.maxsum.constant kbd.maxsum.variance
#> 0.01503796 0.01503796
## get all test result:
res[["complete.info"]][["p.value"]]
#> kbd.sum.constant.pvalue kbd.sum.variance.pvalue
#> 0.91 0.91
#> kbd.max.constant.pvalue kbd.max.variance.pvalue
#> 0.92 0.92
#> kbd.maxsum.constant.pvalue kbd.maxsum.variance.pvalue
#> 0.92 0.92
################ Testing via approximate limit distribution #################
if (FALSE) {
set.seed(1)
n <- 1000
x <- rnorm(n)
y <- rnorm(n)
res <- bd.test(x, y, method = "limit")
bd.test(x, y)
}
################ Formula interface ################
## Two-sample test
bd.test(extra ~ group, data = sleep)
#>
#> 2-sample Ball Divergence Test (Permutation)
#>
#> data: extra by group
#> number of observations = 20, group sizes: 10 10
#> replicates = 99, weight: constant
#> bd.constant = 0.0895, p-value = 0.32
#> alternative hypothesis: distributions of samples are distinct
#>
## K-sample test
bd.test(Sepal.Width ~ Species, data = iris)
#>
#> 3-sample Ball Divergence Test (Permutation)
#>
#> data: Sepal.Width by Species
#> number of observations = 150, group sizes: 50 50 50
#> replicates = 99, weight: constant, kbd.type: sum
#> kbd.sum.constant = 0.48817, p-value = 0.01
#> alternative hypothesis: distributions of samples are distinct
#>
bd.test(Sepal.Width ~ Species, data = iris, kbd.type = "max")
#>
#> 3-sample Ball Divergence Test (Permutation)
#>
#> data: Sepal.Width by Species
#> number of observations = 150, group sizes: 50 50 50
#> replicates = 99, weight: constant, kbd.type: max
#> kbd.max.constant = 0.4618, p-value = 0.01
#> alternative hypothesis: distributions of samples are distinct
#>