| Type: | Package |
| Title: | Chi-Plots for Assessing Bivariate and Multivariate Dependence |
| Version: | 0.1.0 |
| Description: | Graphical methods for assessing dependence. The chi-plot of Fisher and Switzer (1985) <doi:10.1093/biomet/72.2.253> and (2001) <doi:10.1198/000313001317098248> supplements a scatterplot of two variables, producing characteristic patterns for different forms of association. Its multivariate extension (Fisher and Lee, 2026) uses generalized orthants and data depth to explore whether a multivariate distribution factorizes into independent blocks of variables, with permutation tests and guidelines. Functions are provided for single chi-plots, a scatterplot matrix with chi-plots above the diagonal, multivariate chi-plots for a given partition of the variables, and a search over all partitions. Computation-intensive parts are written in C. |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| Encoding: | UTF-8 |
| Depends: | R (≥ 4.0.0) |
| Imports: | graphics, grDevices, stats |
| Suggests: | fda.usc |
| LazyData: | true |
| NeedsCompilation: | yes |
| Packaged: | 2026-10-23 04:35:39 UTC; Nick |
| Author: | Nicholas I. Fisher [aut, cre, cph], Alan J. Lee [aut], ValueMetrics Australia [cph] (copyright holder of the geochem data) |
| Maintainer: | Nicholas I. Fisher <nif@valuemetrics.com.au> |
| Repository: | CRAN |
| Date/Publication: | 2026-11-06 17:10:11 UTC |
Chi-Plots for Assessing Bivariate and Multivariate Dependence
Description
The chi-plot (Fisher and Switzer, 1985, 2001) is a graphical aid to interpreting a scatterplot of two variables: under independence the points form a horizontal band, and different forms of association produce characteristically different patterns. Fisher and Lee (2026) extend the idea to multivariate data, to explore whether a multivariate distribution factorizes into independent blocks of variables.
Details
The main functions are:
chiplota chi-plot for two variables;
chipairsa scatterplot matrix with the corresponding chi-plots above the diagonal;
chimultchi- and lambda-values, permutation tests and the multivariate chi-plot for a given partition of the variables into blocks;
chiparta search over all partitions of the variables, keeping those that show a significant departure from independence;
chidepththe data depth functions used for the lambda-values of multivariate chi-plots.
The calculations of chi-values are carried out in compiled C code. All other code uses base R only.
Author(s)
Nicholas I. Fisher and Alan J. Lee. Maintainer: Nicholas I. Fisher <nif@valuemetrics.com.au>
References
Fisher, N. I. and Switzer, P. (1985). Chi-plots for assessing dependence. Biometrika, 72, 253–265. doi:10.1093/biomet/72.2.253
Fisher, N. I. and Switzer, P. (2001). Graphical assessment of dependence: is a picture worth a hundred tests? The American Statistician, 55, 233–239. doi:10.1198/000313001317098248
Fisher, N. I. and Lee, A. J. (2026). Chi-plots for assessing multivariate dependence. Submitted to Journal of Computational and Graphical Statistics.
Data Depth for Multivariate Chi-Plots
Description
Calculates the data depth of each row of a data matrix with respect to the
whole sample. These depths are the basis of the lambda-values in
chimult.
Usage
chidepth(X, depth = c("RP", "TD", "PD", "MhD"), Nsim = 100)
Arguments
X |
a numeric matrix without missing values. |
depth |
the depth function: one of the names below, or a function. |
Nsim |
the number of random directions for |
Details
All the depth functions are implemented in base R:
"RP"random projection depth: the average, over
Nsimrandom directions, of the univariate halfspace depth of the projected data. The directions are generated as infda.usc::mdepth.RP, so the results are identical for the same random number seed. This is the default."TD"the average of the univariate halfspace (Tukey) depths of the coordinates, as
fda.usc::mdepth.TD. Note that this is not the exact multivariate Tukey depth."PD"projection depth (Zuo and Serfling, 2000),
1 / (1 + O(x))with outlyingnessO(x) = \max_u |u^T x - \mathrm{med}(u^T X)| / \mathrm{MAD}(u^T X), the maximum being taken overNsimrandom directions."MhD"Mahalanobis depth,
1 / (1 + d^2)withdthe Mahalanobis distance from the mean, asfda.usc::mdepth.MhD. This is very fast but parametric.
The names "mdepth.RP", "mdepth.TD", "mdepth.MhD" and
"Projection" are also accepted.
A user-specified depth must be a function of the data matrix that
returns one depth per row, either as a numeric vector or as a list with
component dep. For example, function(X) fda.usc::mdepth.RP(X,
proj = 500)$dep, or a function calling depth() in package
DepthProc.
Value
A numeric vector of depths, one for each row of X.
References
Zuo, Y. and Serfling, R. (2000). General notions of statistical depth function. The Annals of Statistics, 28, 461–482.
See Also
Examples
set.seed(1)
X <- matrix(rnorm(200), 100, 2)
d <- cbind(RP = chidepth(X, "RP"), TD = chidepth(X, "TD"),
PD = chidepth(X, "PD"), MhD = chidepth(X, "MhD"))
round(cor(d, method = "spearman"), 2)
## a user-supplied depth: inverse distance from the coordinatewise median
chidepth(X[1:5, ], function(X) 1 / (1 + sqrt(rowSums(t(t(X) - apply(X, 2, median))^2))))
Multivariate Chi-Plot for a Partition of the Variables
Description
For a multivariate sample and a partition of the variables into blocks,
chimult calculates the chi- and lambda-values of Fisher and Lee (2026),
permutation tests of independence of the blocks, and the material for the
multivariate chi-plot, which is drawn by plot.
Usage
chimult(Data, D, nperm = 100, Nsim = 100, depth = "RP", jitter = NULL,
jitter.amount = 0.25, plot = FALSE, verbose = TRUE, ...)
## S3 method for class 'chimult'
plot(x, pc.level = 0.95, main = "", col1 = "red",
col2 = "blue", pt = 12, box = TRUE, cex = NULL, mar = c(4, 4, 2, 2),
guide.option = 1, del = 0.2, ...)
## S3 method for class 'chimult'
print(x, ...)
Arguments
Data |
a numeric matrix or data frame ( |
D |
the block sizes, in column order: for example, if |
nperm |
the number of random permutations used for the p-values and null distributions. |
Nsim |
the number of random directions for the |
depth |
the data depth used for the lambda-values: |
jitter, jitter.amount |
jittering to break ties, for example for ordered
categorical variables: |
plot |
logical: draw the chi-plot? |
verbose |
logical: report removed observations and jittered variables? |
... |
for |
x |
an object of class |
pc.level |
probability level for the guidelines. |
main |
title of the chi-plot. |
col1, col2 |
colours of the horizontal guidelines and of the vertical reference lines. |
pt |
point size of the text listing the groups. |
box |
logical: draw a box around the list of groups? |
cex |
size of the points; by default chosen from the sample size. |
mar |
plot margins, as in |
guide.option |
the horizontal guidelines: |
del |
tolerance used by |
Details
Observations with missing values are removed. Each column is centred at its median and divided by its interquartile range.
For each observation u_i, the generalized orthant is the set of
v with v_j \le u_{ij} if u_{ij} > 0 and v_j > u_{ij}
otherwise. With H_i the proportion of the sample in this orthant, and
H_{1i}, \dots, H_{ki} the proportions in the corresponding orthants for
the variables of each block, the chi-value is
\chi_i = \sqrt{n}\,(H_i - P_i) / \{P_i (1 - P_i S_i)\}^{1/2},
where P_i = \prod_l H_{li} and
S_i = 1 + \sum_l (1 - H_{li}) / H_{li}. Under independence of the blocks
the chi-values are approximately standard normal. The lambda-value of each
observation is its data depth, transformed by the empirical distribution
function of the depths.
The null distributions are estimated by permuting the rows of blocks
1, \dots, k-1, keeping the rows within each block together.
sigP.chi is the proportion of permutations whose mean squared
chi-value is at least that of the data; sigP.lam is the p-value of a
two-sample Kolmogorov–Smirnov test comparing the data depths with those of
the permuted data.
The plot shows the variables in each group, the chi-plot, and, if
sigP.lam <= 1 - pc.level, a Q-Q plot of the data depths against their
permutation distribution.
With the same random number seed, chimult gives the same results as
the authors' original chimult.lam function with
fda.usc::mdepth.RP.
Value
An object of class "chimult", a list with components
chi |
the chi-values of the data. |
chisq.actual |
the mean of the squared chi-values. |
chi.values.perm |
the chi-values of the permuted data sets. |
chisq.values.perm |
the mean squared chi-values of the permuted data sets. |
sigP.chi |
the permutation p-value of the mean squared chi-value. |
lambda.actual |
the data depths of the observations. |
lambda |
the lambda-values: the data depths transformed by their empirical distribution function. |
lambda.values.perm |
the data depths of the permuted data sets. |
sigP.lam |
the p-value of the Kolmogorov–Smirnov test for the depths. |
X |
the centred and scaled data. |
D, k |
the block sizes and the number of blocks. |
depth, nperm, Nsim |
the settings used. |
n.removed, rows |
the number of observations removed because of missing
values, and the rows of |
jittered |
the names of jittered variables. |
call |
the call. |
References
Fisher, N. I. and Lee, A. J. (2026). Chi-plots for assessing multivariate dependence. Submitted to Journal of Computational and Graphical Statistics.
See Also
chipart to search over partitions;
chidepth; chiplot.
Examples
## Two independent blocks of two correlated normal variables
set.seed(161225)
n <- 200
z1 <- matrix(rnorm(2 * n), n) %*% chol(matrix(c(1, 0.5, 0.5, 1), 2))
z2 <- matrix(rnorm(2 * n), n) %*% chol(matrix(c(1, 0.7, 0.7, 1), 2))
Data <- data.frame(z1, z2)
colnames(Data) <- paste0("Var.", 1:4)
res <- chimult(Data, D = c(2, 2), nperm = 100)
res
plot(res)
## Dependence between the blocks
Data$Var.3 <- Data$Var.3 + 0.8 * Data$Var.1
res2 <- chimult(Data, D = c(2, 2), nperm = 100)
plot(res2, guide.option = 3)
## Five variables, mutually uncorrelated but with a hole in the data
set.seed(280926)
z <- matrix(rnorm(20000 * 5), ncol = 5)
z <- z[sqrt(rowSums((z - 1)^2)) >= 2.5, ][1:200, ]
res3 <- chimult(z, D = rep(1, 5), nperm = 500)
plot(res3, guide.option = 4, pt = 10)
Scatterplot Matrix with Chi-Plots
Description
A scatterplot matrix, like pairs, with the scatterplots below
the diagonal and the corresponding chi-plots above the diagonal.
Usage
chipairs(Data, labels = NULL, ctrl.lines = 2, jitter = NULL,
jitter.amount = 0.25, cex.points = NULL, pch.type = 19,
dot.col = "black", cex.label = NULL, cex.axis = 0.7,
plgap = 0.2, axes = TRUE, main = NULL, ...)
Arguments
Data |
a numeric matrix or data frame ( |
labels |
variable names for the diagonal; by default the column names. |
ctrl.lines |
control lines on the chi-plots, as in |
jitter, jitter.amount |
jittering of variables to break ties, as in
|
cex.points |
size of the points. By default it is chosen from the number of points and the number of panels. |
pch.type, dot.col |
plotting symbol and colour of the points. |
cex.label |
size of the variable names on the diagonal. |
cex.axis |
size of the axis annotation. |
plgap |
space between panels, in lines of text. |
axes |
logical: draw axes on the outer panels? The scatterplots are annotated on the bottom and left, the chi-plots (on the scale -1 to 1) on the top and right. |
main |
an overall title. |
... |
further graphical parameters passed to |
Details
As in pairs, the panel in row i and column j has
variable j on the horizontal axis and variable i on the vertical
axis. Each pair of variables uses all the observations for which both are
present. The chi-plot is symmetric in the two variables.
Value
NULL, invisibly.
See Also
Examples
chipairs(geochem[, 1:5], main = "geochem")
## a smaller sample, with the points emphasised
chipairs(geochem[1:300, c("Cr2O3", "MgO", "CaO", "Ni")], cex.points = 0.5)
Search All Partitions of the Variables with Multivariate Chi-Plots
Description
chipart enumerates the partitions of the p variables into two or
more blocks, runs chimult for each, and keeps the results for
partitions where either test statistic has p-value less than SigProb.
chi.partitions lists the partitions examined.
Usage
chipart(Data, kfix = 0, SigProb = 0.05, nperm = 100, Nsim = 100,
depth = "RP", nblocks = NULL, nperm.screen = NULL,
screen.level = 0.2, jitter = NULL, jitter.amount = 0.25,
verbose = TRUE)
chi.partitions(p, kfix = 0, nblocks = NULL)
## S3 method for class 'chipart'
plot(x, which = NULL, ask = NULL, ...)
## S3 method for class 'chipart'
print(x, ...)
Arguments
Data |
a numeric matrix or data frame ( |
kfix |
if positive, the first |
SigProb |
the significance level used to select interesting partitions. |
nperm, Nsim, depth |
as in |
nblocks |
if given, only partitions with these numbers of blocks are
examined; for example, |
nperm.screen |
if given, a smaller number of permutations used to screen
all partitions; partitions with either p-value at most |
screen.level |
the screening threshold used with |
jitter, jitter.amount |
jittering to break ties, applied once to the
data before the search, as in |
verbose |
logical: report progress? |
p |
the number of variables. |
x |
an object of class |
which |
partition numbers to plot; by default all interesting partitions. |
ask |
logical: pause before each plot? By default, on interactive devices when there is more than one plot. |
... |
arguments passed to |
Details
The number of partitions grows quickly with p: the Bell numbers are 1,
2, 5, 15, 52, 203, 877, 4140, 21147, 115975, .... The options
kfix, nblocks, nperm.screen and a fast depth such as
depth = "MhD" reduce the computing time.
For each partition the variables are reordered so that the blocks are
contiguous, keeping the original order within each block, and
chimult is called. A partition is “interesting” if
sigP.chi or sigP.lam is less than SigProb. No allowance
is made for multiple testing.
Value
chipart returns an object of class "chipart", a list with
components
summary |
a data frame with one row per partition: the partition number,
the groups, the number of blocks, |
results |
a list of |
partitions |
the partitions: a matrix with one column per partition giving the block number of each variable. |
variables, SigProb, kfix, nperm, nperm.screen, Nsim, depth, n, n.removed, call |
details of the search. |
chi.partitions returns the matrix of partitions.
References
Fisher, N. I. and Lee, A. J. (2026). Chi-plots for assessing multivariate dependence. Submitted to Journal of Computational and Graphical Statistics.
See Also
Examples
## the partitions examined for 4 variables, and with the first kept fixed
chi.partitions(4)
chi.partitions(4, kfix = 1)
## four variables, of which the second and fourth are dependent
set.seed(5)
W <- matrix(rnorm(100 * 4), 100, 4)
W[, 4] <- W[, 4] + W[, 2]
colnames(W) <- paste0("V", 1:4)
res <- chipart(W, nperm = 20, verbose = FALSE)
res
plot(res, which = 3)
## screening with fewer permutations
res2 <- chipart(W, nperm = 200, nperm.screen = 20)
res2$summary
Chi-Plot for Assessing Dependence of Two Variables
Description
chivals calculates the chi- and lambda-values of Fisher and Switzer
(1985) for a bivariate sample; chiplot calculates them and draws the
chi-plot.
Usage
chiplot(x, y = NULL, ctrl.lines = 2, jitter = NULL, jitter.amount = 0.25,
cex.points = NULL, pch.type = 19, dot.col = "black", main = "",
cex.axis = 1, cex.lam = 1.2, plot = TRUE, ...)
chivals(x, y = NULL, jitter = NULL, jitter.amount = 0.25)
## S3 method for class 'chiplot'
plot(x, ctrl.lines = 2, cex.points = NULL, pch.type = 19,
dot.col = "black", main = "", cex.axis = 1, cex.lam = 1.2,
xlab = expression(lambda), ylab = expression(chi),
col.ctrl = "red", lty.ctrl = 1, ...)
## S3 method for class 'chiplot'
print(x, ...)
Arguments
x |
a numeric vector or ordered factor; or, if |
y |
a numeric vector or ordered factor of the same length as |
ctrl.lines |
control lines enclosing, on average, the given percentage of
points under independence: |
jitter |
which variables to jitter, to break ties (for example, for
ordered categorical variables): |
jitter.amount |
size of the jitter, as a fraction (less than 0.5) of the smallest gap between distinct values, so that the order of distinct values is preserved. |
cex.points |
size of the plotted points. The default |
pch.type, dot.col |
plotting symbol and colour of the points. |
main |
title of the plot. |
cex.axis |
size of the axis annotation. |
cex.lam |
size of the axis labels |
plot |
logical: if |
xlab, ylab |
axis labels. |
col.ctrl, lty.ctrl |
colour and line type of the control lines. |
... |
further graphical parameters passed to |
Details
Observations with a missing value in either variable are removed. For each
point (x_i, y_i), let F_i, G_i and H_i be the
proportions of the other n-1 points with x_j \le x_i,
y_j \le y_i, and both, respectively. Then
\chi_i = (H_i - F_i G_i) / \{F_i (1 - F_i) G_i (1 - G_i)\}^{1/2},
\lambda_i = 4\,\mathrm{sign}(\tilde F_i \tilde G_i)\,
\max(\tilde F_i^2, \tilde G_i^2),
where \tilde F_i = F_i - 1/2 and
\tilde G_i = G_i - 1/2. Points with
|\lambda_i| \ge 4\{1/(n-1) - 1/2\}^2, at the edges of the data, are not
plotted. Under independence the points lie in a horizontal band about
\chi = 0, approximately the stated percentage of them between the
control lines at \pm c_p / \sqrt{n}, with
c_p = 1.54, 1.78 and 2.18 for 90%, 95% and 99%.
As in the original program, the sine transformation of the chi-values mentioned by Fisher and Switzer (1985) is not used. The chi- and lambda-values depend only on the ranks of the data.
Value
An object of class "chiplot" (returned invisibly by chiplot): a
list with components
lambda, chi |
the lambda- and chi-values of the plotted points; |
index |
the row numbers, in the original data, of the plotted points; |
n |
the number of complete pairs; |
npts |
the number of points plotted; |
n.missing |
the number of pairs removed because of missing values; |
names |
the names of the two variables. |
References
Fisher, N. I. and Switzer, P. (1985). Chi-plots for assessing dependence. Biometrika, 72, 253–265. doi:10.1093/biomet/72.2.253
Fisher, N. I. and Switzer, P. (2001). Graphical assessment of dependence: is a picture worth a hundred tests? The American Statistician, 55, 233–239. doi:10.1198/000313001317098248
See Also
chipairs for all pairs of variables;
chimult for blocks of variables.
Examples
set.seed(1)
op <- par(mfrow = c(2, 2))
## Independent normal variables
x <- rnorm(100); y <- rnorm(100)
chiplot(x, y, main = "Independence")
## Bivariate normal, correlation 0.7
y <- 0.7 * x + sqrt(1 - 0.7^2) * rnorm(100)
chiplot(x, y, main = "Correlation 0.7")
## Non-monotone association: points near a half circle
x <- rnorm(2000); y <- rnorm(2000)
keep <- y >= 0 & abs(x^2 + y^2 - 1) <= 0.5
chiplot(x[keep][1:100], y[keep][1:100], main = "Half ring")
## Ordered categorical variable: jittered automatically
u <- rnorm(100)
grade <- cut(u + rnorm(100), c(-Inf, -1, 0, 1, Inf), ordered_result = TRUE)
res <- chiplot(u, grade, main = "Ordered categories")
par(op)
res
Geochemical Measurements
Description
Measurements of 11 geochemical constituents on 1000 samples, used to
illustrate chipairs. The values are the ranks of the
measurements within each variable, with tied values given their average rank.
Usage
geochem
Format
A data frame with 1000 rows and 11 numeric columns: TiO2,
Cr2O3, FeO, MnO, MgO, CaO, Ni,
Zn, Ga, Y and Zr.
Source
ValueMetrics Australia. Included with the permission of the copyright holder.
Examples
summary(geochem[, 1:4])
chipairs(geochem[, c("Cr2O3", "MgO", "Ni")])