diff --git a/NEWS.md b/NEWS.md index babdd92..81b8da4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# corrplot (development version) + +## Changes + + * Document `transKeepSign`, which was previously described by a + truncated note, and illustrate it in the examples (#287). + # corrplot 0.95 ## Changes diff --git a/R/corrplot.R b/R/corrplot.R index cb2b4a5..2b6b66a 100644 --- a/R/corrplot.R +++ b/R/corrplot.R @@ -168,7 +168,33 @@ #' transforming non-corr matrix for plotting. #' Only valid when \code{is.corr = FALSE}. The default value is \code{TRUE}. #' -#' NOTE: If \code{FALSE},the non-corr matrix will be +#' \code{corrplot()} maps the values of the matrix onto the colours in +#' \code{col} by rescaling them to the interval [0, 1]. For a matrix that is +#' not a correlation matrix, this parameter controls how that rescaling is +#' done when the matrix contains both negative and positive values. +#' +#' If \code{TRUE}, the values are divided by \code{max(abs(col.lim))}: they +#' keep their sign and zero stays at the midpoint of the colour scale, so a +#' diverging palette is centred on zero, just as it is for a correlation +#' matrix. This is what you want when zero is a meaningful reference point +#' (e.g. differences, log ratios or z-scores). Note that the colour scale +#' then saturates at \code{max(abs(col.lim))}, so with an asymmetric +#' \code{col.lim} the side with the smaller range uses only part of the +#' palette. +#' +#' If \code{FALSE}, the values are rescaled linearly so that +#' \code{col.lim[1]} is mapped to the first colour in \code{col} and +#' \code{col.lim[2]} to the last one: the whole palette is spread over the +#' whole data range and the sign of the values is lost, i.e. zero is no +#' longer tied to the middle of the palette. A sequential palette is usually +#' a better fit in this case. Since the rescaled values are all non-negative, +#' the glyph size would carry no sign information, so the methods +#' \code{'circle'}, \code{'square'}, \code{'ellipse'}, \code{'shade'} and +#' \code{'pie'} are rejected with an error. +#' +#' The parameter has no effect on a matrix whose values are all negative or +#' all positive: such a matrix is always rescaled linearly over +#' \code{col.lim}, whatever the value of \code{transKeepSign}. #' #' @param p.mat Matrix of p-value, if \code{NULL}, parameter \code{sig.level}, #' \code{insig}, \code{pch}, \code{pch.col}, \code{pch.cex} are invalid. diff --git a/man/corrplot.Rd b/man/corrplot.Rd index 3b0324f..5797be1 100644 --- a/man/corrplot.Rd +++ b/man/corrplot.Rd @@ -220,7 +220,34 @@ negative.} transforming non-corr matrix for plotting. Only valid when \code{is.corr = FALSE}. The default value is \code{TRUE}. - NOTE: If \code{FALSE},the non-corr matrix will be} + \code{corrplot()} maps the values of the matrix onto the colours in + \code{col} by rescaling them to the interval [0, 1]. For a matrix that is + not a correlation matrix, this parameter controls how that rescaling is + done when the matrix contains both negative and positive values. + + If \code{TRUE}, the values are divided by \code{max(abs(col.lim))}: they + keep their sign and zero stays at the midpoint of the colour scale, so a + diverging palette is centred on zero, just as it is for a correlation + matrix. This is what you want when zero is a meaningful reference point + (e.g. differences, log ratios or z-scores). Note that the colour scale + then saturates at \code{max(abs(col.lim))}, so with an asymmetric + \code{col.lim} the side with the smaller range uses only part of the + palette. + + If \code{FALSE}, the values are rescaled linearly so that + \code{col.lim[1]} is mapped to the first colour in \code{col} and + \code{col.lim[2]} to the last one: the whole palette is spread over the + whole data range and the sign of the values is lost, i.e. zero is no + longer tied to the middle of the palette. A sequential palette is usually + a better fit in this case. Since the rescaled values are all non-negative, + the glyph size would carry no sign information, so the methods + \code{'circle'}, \code{'square'}, \code{'ellipse'}, \code{'shade'} and + \code{'pie'} are rejected with an error. + + The parameter has no effect on a matrix whose values are all negative or + all positive: such a matrix is always rescaled linearly over + \code{col.lim}, whatever the value of \code{transKeepSign}. +} \item{p.mat}{Matrix of p-value, if \code{NULL}, parameter \code{sig.level}, \code{insig}, \code{pch}, \code{pch.col}, \code{pch.cex} are invalid.} diff --git a/tests/testthat/test-corrplot.R b/tests/testthat/test-corrplot.R index 6579eda..e801c2d 100644 --- a/tests/testthat/test-corrplot.R +++ b/tests/testthat/test-corrplot.R @@ -109,6 +109,32 @@ test_that('Non-correlation matrix', { expect_true(is.data.frame(corrplot(M, is.corr = FALSE)$corrPos)) }) +test_that('Testing `transKeepSign` parameter (issue #287)', { + M = matrix(c(-0.5, 0, 0.25, 1), nrow = 2) + lim = c(-0.5, 1) + + # TRUE (default): the values keep their sign, zero stays at zero + expect_equal(unname(corrplot(M, is.corr = FALSE, col.lim = lim, + method = 'color')$corr), M) + + # FALSE: col.lim[1] is mapped to 0 and col.lim[2] to 1 + expect_equal(unname(corrplot(M, is.corr = FALSE, col.lim = lim, + method = 'color', + transKeepSign = FALSE)$corr), + (M - lim[1]) / diff(lim)) + + # without the sign, the value-based glyph methods do not make sense + expect_error(corrplot(M, is.corr = FALSE, col.lim = lim, + transKeepSign = FALSE, method = 'circle'), + regexp = 'transKeepSign = FALSE') + + # the parameter does not matter for a matrix with a single sign + Mpos = matrix(seq(1, 10, length.out = 100), nrow = 10) + expect_equal(unname(corrplot(Mpos, is.corr = FALSE, method = 'color', + transKeepSign = FALSE)$corr), + unname(corrplot(Mpos, is.corr = FALSE, method = 'color')$corr)) +}) + test_that('Try different ordering', { M = cor(mtcars) diff --git a/vignettes/example-corrplot.R b/vignettes/example-corrplot.R index 9d24be8..7ec0604 100644 --- a/vignettes/example-corrplot.R +++ b/vignettes/example-corrplot.R @@ -91,6 +91,17 @@ corrplot(M*2, is.corr = FALSE, col.lim = c(-2, 2)) corrplot(M*2, is.corr = FALSE, col.lim = c(-2, 2) * 2) corrplot(M*2, is.corr = FALSE, col.lim = c(-2, 2) * 4) +# transKeepSign controls how such a matrix is rescaled to [0, 1] +# TRUE (default): values are divided by max(abs(col.lim)), so zero stays at +# the middle of the colour scale and the sign is kept +# FALSE: values are rescaled linearly over col.lim, the whole palette is used +# but the sign is lost, so 'circle', 'square', 'ellipse', 'shade' and 'pie' +# are not available +corrplot(M, is.corr = FALSE, col.lim = c(-1, 1), method = 'color', + transKeepSign = TRUE) +corrplot(M, is.corr = FALSE, col.lim = c(-1, 1), method = 'color', + transKeepSign = FALSE) + ## 0.5~0.6 corrplot(abs(M)/10+0.5, col = COL1('Greens', 10)) corrplot(abs(M)/10+0.5, is.corr = FALSE, col.lim = c(0.5, 0.6), col = COL1('YlGn', 10))