Nothing
#' Make a correlation heatmap with ggplot2.
#'
#' Make a correlation heatmap from input matrices. Uses a diverging colour scale centered around 0.
#'
#' @inheritParams gghm
#'
#' @param x Matrix or data frame in wide format containing the columns to correlate against each other or against the columns in `y`.
#' @param y Optional matrix or data frame in wide format containing columns to correlate with the columns in `x`.
#' @param cor_method String specifying correlation method to use in the `stats::cor()` function. Default is 'pearson'.
#' @param cor_use String specifying the `use` argument of `stats::cor()`, which defines how to deal with missing values. Default is 'everything'.
#' @param cor_in Logical indicating if the input data contains correlation values and any correlation computations (including p-values) should be skipped. Default is FALSE.
#' @param high Colour to use for the highest value of the colour scale.
#' @param mid Colour to use for 0 in the colour scale.
#' @param low Colour to use for the lowest value of the colour scale.
#' @param midpoint Value for the middle point of the colour scale.
#' @param col_scale Scale to use for cell colours. If NULL (default), a divergent scale is constructed from the `high`, `mid`, `low`, `midpoint`, `limits`, and `bins` arguments.
#' These arguments are ignored if a `ggplot2::scale_*` function is provided instead. If a string, the corresponding Brewer or Viridis scale is used.
#' A string with a scale name with "rev_" in the beginning or "_rev" at the end will result in the reversed scale.
#' In mixed layouts, can also be a list of length two containing the two scales to use.
#' @param col_name String to use for the correlation scale. If NULL (default) the text will depend on the correlation method. Can be two values in mixed layouts for dual scales.
#' @param p_values Logical indicating if p-values should be calculated. Use with `p_thresholds` to mark cells, and/or `return_data` to get the p-values in the output data.
#' @param p_adjust String specifying the multiple testing adjustment method to use for the p-values (default is "none"). Passed to `stats::p.adjust()`.
#' @param p_thresholds Named numeric vector specifying p-value thresholds (in ascending order) to mark. The last element must be 1 or higher (to set the upper limit).
#' Names must be unique, but one element can be left unnamed (by default 1 is unnamed, meaning values between the threshold closest to 1 and 1 are not marked in the plot).
#' If NULL, no thresholding is done and p-value intervals are not marked with symbols.
#' @param layout String specifying the layout of the output heatmap. Possible layouts include
#' 'topleft', 'topright', 'bottomleft', 'bottomright', or the 'whole'/'full' heatmap (default and only possible option if the matrix is asymmetric).
#' A combination of the first letters of each word also works (i.e. f, w, tl, tr, bl, br).
#' If layout is of length two with two opposing triangles, a mixed layout will be used. For mixed layouts,
#' `mode` needs a vector of length two (applied in the same order as layout). See details of `gghm()` for more information.
#' @param include_diag Logical indicating if the diagonal cells should be plotted (if the matrix is symmetric).
#' @param na_remove Logical indicating if NA values in the heatmap should be omitted (meaning no cell border is drawn). This does not affect how
#' NAs are handled in the correlation computations, use the `cor_use` argument for NA handling in correlation.
#' @param return_data Logical indicating if the data used for plotting (i.e. the correlation values and, if computed, clustering and p-values) should be returned.
#' @param legend_order Integer vector specifying the order of legends (first value is for the first legend, second for the second, etc). The default (NULL) shows all but size legends.
#' NAs hide the corresponding legends, a single NA hides all. Ignored for `ggplot2` scale objects in `col_scale` and `size_scale`.
#' @param size_range Numeric vector of length 2, specifying lower and upper ranges of shape sizes. Ignored if `size_scale` is not NULL.
#' @param size_scale `ggplot2::scale_size_*` call to use for size scaling if `mode` is a number from 1 to 25 (R pch).
#' The default behaviour (NULL) is to use a continuous scale with the absolute values of the correlation.
#' @param cell_labels Logical specifying if the cells should be labelled with the correlation values. Alternatively, a matrix or data frame with the same shape and dimnames as `x`
#' containing values to write in the cells. If mode is `text`, the cell label colours will scale with the correlation values and `cell_label_col` is ignored.
#' @param cell_label_p Logical indicating if, when `cell_labels` is `TRUE`, p-values should be written instead of correlation values.
#' @param cell_label_col Colour to use for cell labels, passed to `ggplot2::geom_text()`.
#' @param cell_label_size Size of cell labels, used as the `size` argument in `ggplot2::geom_text()`.
#' @param annot_rows_params,annot_cols_params Named list with parameters for row or column annotations to overwrite the defaults set by the `annot_*` arguments, each name corresponding to the `*` part
#' (see details of `gghm()` for more information).
#' @param dend_rows_params,dend_cols_params Named list for row or column dendrogram parameters. See details of `gghm()` for more information.
#' @param dend_rows_extend,dend_cols_extend Named list or functional sequence for specifying `dendextend` functions to apply to the row or column dendrogram. See details of `gghm()` and `ggcorrhm()` for usage.
#'
#' @return The correlation heatmap as a `ggplot` object.
#' If `return_data` is TRUE the output is a list containing the plot (named 'plot'),
#' the correlations ('plot_data', with factor columns 'row' and 'col' and a column 'value' containing the cell values),
#' and the result of the clustering ('row_clustering' and 'col_clustering', if clustered).
#' If p-values were calculated, two additional columns named 'p_val' and 'p_adj' are included in 'plot_data', containing nominal and adjusted p-values.
#' If the layout is mixed, an extra factor column named 'layout' is included, showing which triangle each cell belongs to.
#'
#' @export
#'
#' @details
#'
#' `ggcorrhm()` makes it convenient to make correlation heatmaps, taking the input matrix or data frame to visualise the correlations between columns with the `gghm()` function.
#' The input values can either be one matrix or data frame with columns to correlate with each other, or two
#' matrices or data frames with columns to correlate between the matrices. No rownames are needed, but
#' if two matrices are provided they should have the same number of rows and the rows should be ordered in a meaningful way
#' (i.e. same sample/individual/etc in the same row in both).
#'
#' Row and column names are displayed in the diagonal by default if the correlation matrix is symmetric (only `x` is provided or `x` and `y` are identical).
#'
#' The colour scale is set to be a diverging gradient around 0, with options to change the `low`, `mid`, and `high` colours, the `midpoint`, and the `limits` (using the arguments
#' of the same names). The `bins` argument converts the scale to a discrete scale divided into `bins` equally distributed bins (if an integer the breaks may be at strange numbers,
#' if a double the number of bins may be different but the breaks are at nicer numbers). These arguments can be of length two (`limits` a list of length two) two apply
#' to each triangle in a mixed layout (detailed more in the details section of `gghm()`). The `size_range` argument (for size scales) can also be a list of length two like `limits`.
#'
#' The size scale, used when a numeric cell shape is specified, is set to vary the shape size between 4 and 10 (can be changed with the `size_range` argument)
#' and to transform the values to absolute values (so that both positive and negative correlations are treated equally).
#' This behaviour can be overwritten by setting `size_scale` to another `ggplot2::scale_size_*` function with the desired
#' arguments, or `ggplot2::scale_size()` for no special behaviour. `ggplot2::scale_size_area()` also scales with the absolute value,
#' but only the upper size limit can be set.
#' When the absolute value transformation is used the legend for sizes loses its meaning (only displaying positive values)
#' and is therefore set to not be shown if `legend_order` is NULL.
#'
#' For symmetric correlation matrices, the dendrogram customisation arguments `dend_rows_extend` and `dend_cols_extend` work best with functions that only change the dendrogram
#' cosmetically such as the colours, linetypes or node shapes. While it is possible to reorder (using e.g. 'rotate', 'ladderize') or prune (using e.g. 'prune'),
#' anything that changes the structure of the dendrogram may end up looking strange for symmetric matrices if
#' only applied to one dimension (e.g. the diagonal may not be on the diagonal, triangular or mixed layouts may not work).
#' The same applies if the `cluster_rows` and `cluster_cols` arguments are `hclust` or `dendrogram` objects.
#'
#' @examples
#' # Basic usage
#' ggcorrhm(mtcars)
#'
#' # With two matrices
#' ggcorrhm(iris[1:32, -5], mtcars)
#'
#' # Different layout
#' ggcorrhm(mtcars, layout = "br")
#'
#' # With clustering
#' ggcorrhm(mtcars, layout = "tl", cluster_rows = TRUE, cluster_cols = TRUE)
#'
#' # With annotation
#' set.seed(123)
#' annot <- data.frame(.names = colnames(mtcars),
#' annot1 = rnorm(ncol(mtcars)),
#' annot2 = sample(letters[1:3], ncol(mtcars), TRUE))
#' ggcorrhm(mtcars, layout = "tr", annot_cols_df = annot)
#'
#' # Both
#' ggcorrhm(mtcars, layout = "full", cluster_rows = TRUE, cluster_cols = TRUE,
#' annot_rows_df = annot[, -3], annot_cols_df = annot[, -2])
#'
#' # Mixed layout
#' ggcorrhm(mtcars, layout = c("tl", "br"))
#'
ggcorrhm <- function(x, y = NULL, cor_method = "pearson", cor_use = "everything", cor_in = FALSE,
high = "sienna2", mid = "white", low = "skyblue2", midpoint = 0, limits = c(-1, 1), bins = NULL,
layout = "full", mode = if (length(layout) == 1) "heatmap" else c("heatmap", "text"),
include_diag = TRUE, na_col = "grey50", na_remove = FALSE, return_data = FALSE,
col_scale = NULL, col_name = NULL,
size_range = c(4, 10), size_scale = NULL, size_name = NULL,
legend_order = NULL,
p_values = FALSE, p_adjust = "none", p_thresholds = c("***" = 0.001, "**" = 0.01, "*" = 0.05, 1),
cell_labels = FALSE, cell_label_p = FALSE, cell_label_col = "black", cell_label_size = 3, cell_label_digits = 2,
cell_bg_col = "white", cell_bg_alpha = 0,
border_col = "grey", border_lwd = 0.1, border_lty = 1,
show_names_diag = TRUE, names_diag_params = NULL,
show_names_x = FALSE, names_x_side = "top", show_names_y = FALSE, names_y_side = "left",
annot_rows_df = NULL, annot_cols_df = NULL,
annot_rows_col = NULL, annot_cols_col = NULL,
annot_rows_side = "right", annot_cols_side = "bottom",
annot_dist = 0.2, annot_gap = 0, annot_size = 0.5,
annot_border_col = if (length(border_col) == 1) border_col else "grey",
annot_border_lwd = if (length(border_lwd) == 1) border_lwd else 0.5,
annot_border_lty = if (length(border_lty) == 1) border_lty else 1,
annot_na_col = na_col, annot_na_remove = na_remove,
annot_rows_params = NULL, annot_cols_params = NULL,
show_annot_names = TRUE, annot_names_size = 3,
annot_rows_names_side = "bottom", annot_cols_names_side = "left",
annot_rows_names_params = NULL, annot_cols_names_params = NULL,
annot_rows_name_params = NULL, annot_cols_name_params = NULL,
cluster_rows = FALSE, cluster_cols = FALSE,
cluster_distance = "euclidean", cluster_method = "complete",
show_dend_rows = TRUE, show_dend_cols = TRUE, dend_rows_side = "right", dend_cols_side = "bottom",
dend_col = "black", dend_dist = 0, dend_height = 0.3, dend_lwd = 0.3, dend_lty = 1,
dend_rows_params = NULL, dend_cols_params = NULL,
dend_rows_extend = NULL, dend_cols_extend = NULL,
split_rows = NULL, split_cols = NULL) {
# Perform some input argument checks
check_logical(return_data = return_data)
check_layout(layout, mode)
if (length(mode) > 1) {
check_logical(p_values = p_values, list_allowed = TRUE)
check_logical(cell_label_p = cell_label_p, list_allowed = TRUE)
} else {
check_logical(p_values = p_values, list_allowed = FALSE)
check_logical(cell_label_p = cell_label_p, list_allowed = FALSE)
}
if (any(unlist(p_values))) {
if (!is.numeric(p_thresholds) && !is.null(p_thresholds)) {
cli::cli_abort("{.var p_thresholds} must be a named {.cls numeric} vector or NULL.",
class = "p_thr_class_error")
} else if (!is.null(p_thresholds)) {
if (any(is.na(p_thresholds))) cli::cli_abort("{.var p_thresholds} should not contain any missing values.", class = "p_thr_error")
if (any(p_thresholds <= 0)) cli::cli_abort("Values in {.var p_thresholds} must be above 0.", class = "p_thr_error")
if (p_thresholds[length(p_thresholds)] < 1) cli::cli_abort("The last value of {.var p_thresholds} must be 1 or larger.", class = "p_thr_error")
if (is.null(names(p_thresholds))) cli::cli_abort("{.var p_thresholds} must have named elements to be used as symbols (up to one unnamed).", class = "p_thr_error")
if (any(duplicated(names(p_thresholds)))) cli::cli_abort("Symbols (the names) of {.var p_thresholds} must be unique.", class = "p_thr_error")
}
}
# Skip correlation (and p-value) computation if cor_in is TRUE
check_logical(cor_in = cor_in)
if (isTRUE(cor_in)) {
cor_mat <- x
cor_mat_dat <- NULL
p_values <- FALSE
cell_label_p <- FALSE
} else {
cor_mat <- if (is.null(y)) {
cor(x, method = cor_method, use = cor_use)
} else {
cor(x, y, method = cor_method, use = cor_use)
}
# Placeholder for p-value data that may be replaced
cor_mat_dat <- NULL
if (!any(unlist(p_values))) {
if (is.null(y)) {
cor_mat <- cor(x, method = cor_method, use = cor_use)
} else {
cor_mat <- cor(x, y, method = cor_method, use = cor_use)
}
} else {
cor_mat <- test_cor(x, y, method = cor_method, use = cor_use, p_adj_method = p_adjust)
# Keep the data for later plotting
cor_mat_dat <- cor_mat
# Get wide format correlation matrix
cor_mat <- shape_mat_wide(dplyr::select(cor_mat, -"p_val", -"p_adj"))
}
}
# Check annotation data frames (must be done before making scales)
if (!is.null(annot_rows_df)) {
annot_rows_df <- check_annot_df(annot_rows_df, rownames(cor_mat), "annot_rows_df")
}
if (!is.null(annot_cols_df)) {
annot_cols_df <- check_annot_df(annot_cols_df, colnames(cor_mat), "annot_cols_df")
}
# Prepare parameters for two-length layouts (separate from what is done in gghm)
if (length(layout) == 2) {
p_values <- prepare_mixed_param(p_values, "p_values")
cell_labels <- prepare_mixed_param(cell_labels, "cell_labels")
cell_label_p <- prepare_mixed_param(cell_label_p, "cell_label_p")
cell_label_digits <- prepare_mixed_param(cell_label_digits, "cell_label_digits")
}
# Prepare cell labels
cell_labels <- prepare_cell_labels(mode, cell_labels, p_values, cell_label_p,
cell_label_digits, p_thresholds, cor_mat_dat)
# Name of fill legend
scale_names <- switch(cor_method,
"pearson" = "Pearson r",
"spearman" = "Spearman\nrho",
"kendall" = "Kendall\ntau")
if (is.null(col_name)) {
col_name <- scale_names
}
if (is.null(size_name)) {
size_name <- scale_names
}
# Don't display names on the diagonal if the plot is non-symmetric as it will cause
# new ghost columns to be added to draw the names where row == col
if (!isSymmetric(as.matrix(cor_mat))) {
show_names_diag <- FALSE
# Also display x and y names by default, but remove if specified as FALSE (when specified as a named argument)
show_names_x <- eval(replace_default(list("show_names_x" = TRUE), as.list(sys.call()))$show_names_x)
show_names_y <- eval(replace_default(list("show_names_y" = TRUE), as.list(sys.call()))$show_names_y)
}
# Get scales and their orders
scale_order <- make_legend_order(mode = mode,
col_scale = col_scale,
size_scale = size_scale, annot_rows_df = annot_rows_df,
annot_cols_df = annot_cols_df,
bins = bins, limits = limits,
high = high, mid = mid, low = low, na_col = na_col,
midpoint = midpoint, size_range = size_range,
legend_order = legend_order)
# Prepare scales for mixed layouts
if (length(layout) == 2) {
bins <- prepare_mixed_param(bins, "bins")
limits <- prepare_mixed_param(limits, "limits")
midpoint <- prepare_mixed_param(midpoint, "midpoint")
size_range <- prepare_mixed_param(size_range, "size_range")
high <- prepare_mixed_param(high, "high")
mid <- prepare_mixed_param(mid, "mid")
low <- prepare_mixed_param(low, "low")
na_col <- prepare_mixed_param(na_col, "na_col")
col_name <- prepare_mixed_param(col_name, "col_name")
col_scale <- prepare_mixed_param(col_scale, "col_scale")
size_name <- prepare_mixed_param(size_name, "size_name")
size_scale <- prepare_mixed_param(size_scale, "size_scale")
}
# Hide some legends by default in the main plot
if (is.null(legend_order)) {
# Hide all size legends, default is transformed without a way to map back to values (abs)
if ("size" %in% scale_order[["main_scales"]][["scales"]]) {
scale_order[["main_scales"]][["order"]][which(scale_order[["main_scales"]][["scales"]] == "size")] <- NA
}
if (length(layout) == 2) {
# Use two if statements as the next one needs layout to be length two
# If a mixed layout with different aesthetics is used and
if (all(c("col", "fill") %in% scale_order[["main_scales"]][["scales"]]) &
# the default or just one colour scale is used (not a scale object since it will be aesthetic-specific)
(all(sapply(col_scale, is.null)) |
(identical(col_scale[[1]], col_scale[[2]]) & is.character(col_scale[[1]])))
) {
# Hide one of the legends (col)
scale_order[["main_scales"]][["order"]][which(scale_order[["main_scales"]][["scales"]] == "col")] <- NA
}
}
}
# Generate the necessary scales
main_scales <- prepare_scales(scale_order = scale_order, context = "ggcorrhm",
layout = layout,
val_type = "continuous",
col_scale = col_scale, col_name = col_name,
size_scale = size_scale, size_name = size_name,
bins = bins, limits = limits,
high = high, mid = mid, low = low, midpoint = midpoint,
size_range = size_range, na_col = na_col)
# Annotation scales
annot_scales <- prepare_scales_annot(scale_order = scale_order, na_col = annot_na_col,
annot_rows_df = annot_rows_df, annot_cols_df = annot_cols_df,
annot_rows_col = annot_rows_col, annot_cols_col = annot_cols_col)
# Generate the scale lists to pass to gghm
col_scale <- extract_scales(main_scales, scale_order, c("fill", "col"), layout)
size_scale <- extract_scales(main_scales, scale_order, "size", layout)
# Call with all arguments to get the tooltips when calling ggcorrhm
cor_plt <- gghm(cor_mat,
na_remove = na_remove,
mode = mode, layout = layout, include_diag = include_diag, return_data = TRUE,
col_scale = col_scale, col_name = col_name,
size_scale = size_scale, size_name = size_name,
border_col = border_col, border_lwd = border_lwd, border_lty = border_lty,
show_names_diag = show_names_diag, names_diag_params = names_diag_params,
show_names_x = show_names_x, names_x_side = names_x_side,
show_names_y = show_names_y, names_y_side = names_y_side,
cell_labels = cell_labels, cell_label_col = cell_label_col,
cell_label_size = cell_label_size, cell_label_digits = cell_label_digits,
cell_bg_col = cell_bg_col, cell_bg_alpha = cell_bg_alpha,
annot_rows_df = annot_rows_df, annot_cols_df = annot_cols_df,
annot_rows_col = annot_scales[["rows"]], annot_cols_col = annot_scales[["cols"]],
annot_rows_side = annot_rows_side, annot_cols_side = annot_cols_side,
annot_dist = annot_dist, annot_gap = annot_gap,
annot_size = annot_size, show_annot_names = show_annot_names,
annot_border_col = annot_border_col, annot_border_lwd = annot_border_lwd, annot_border_lty = annot_border_lty,
annot_na_col = annot_na_col, annot_na_remove = annot_na_remove,
annot_rows_params = annot_rows_params, annot_cols_params = annot_cols_params,
annot_names_size = annot_names_size,
annot_rows_names_side = annot_rows_names_side, annot_cols_names_side = annot_cols_names_side,
annot_rows_names_params = annot_rows_names_params, annot_cols_names_params = annot_cols_names_params,
annot_rows_name_params = annot_rows_name_params, annot_cols_name_params = annot_cols_name_params,
cluster_rows = cluster_rows, cluster_cols = cluster_cols,
cluster_distance = cluster_distance, cluster_method = cluster_method,
show_dend_rows = show_dend_rows, show_dend_cols = show_dend_cols,
dend_rows_side = dend_rows_side, dend_cols_side = dend_cols_side,
dend_col = dend_col, dend_dist = dend_dist, dend_height = dend_height, dend_lwd = dend_lwd, dend_lty = dend_lty,
dend_rows_params = dend_rows_params, dend_cols_params = dend_cols_params,
dend_rows_extend = dend_rows_extend, dend_cols_extend = dend_cols_extend,
split_rows = split_rows, split_cols = split_cols)
if (return_data & any(unlist(p_values))) {
# Add p-values to output data
cor_plt[["plot_data"]] <- dplyr::left_join(cor_plt[["plot_data"]],
dplyr::select(cor_mat_dat, "row", "col", "p_val", "p_adj"),
by = c("row", "col"))
}
cor_out <- if (return_data) {cor_plt} else {cor_plt[["plot"]]}
return(cor_out)
}
#' Prepare cell labels in ggcorrhm to pass to gghm
#'
#' @keywords internal
#'
#' @param mode Plotting mode.
#' @param cell_labels Cell labels (TRUE, FALSE, matrix, data frame).
#' @param p_values Logical indicating if p-values should be computed.
#' @param cell_label_p Logical indicating if cell labels should be swapped for p-values.
#' @param cell_label_digits Number of digits to display for cell labels.
#' @param p_thresholds P-value thresholds.
#' @param cor_mat_dat Correlation long format data from correlation tests.
#'
#' @returns Object to use as cell_labels in gghm (containing a logical, a matrix/data frame, or a list of length 2 with those things).
#'
prepare_cell_labels <- function(mode, cell_labels, p_values, cell_label_p, cell_label_digits,
p_thresholds = NULL, cor_mat_dat = NULL) {
p_adj <- value <- NULL
# If a matrix or data frame, put in a list
if (is.matrix(cell_labels) | is.data.frame(cell_labels)) {
cell_labels <- list(cell_labels)
}
# If just NULL is passed to mapply the result becomes list()
# so put cell_label_digits in a list if not already, to allow for NULL to not round
# (any other non-numeric also results in no rounding)
if (!is.list(cell_label_digits)) {cell_label_digits <- list(cell_label_digits)}
# Make p symbols if p-values are computed
if (any(unlist(p_values))) {
p_sym <- if (is.numeric(p_thresholds)) {
# Make symbols for p-values
as.character(symnum(x = cor_mat_dat[["p_adj"]],
# Add 0 to set the range of possible values
cutpoints = c(0, p_thresholds),
symbols = names(p_thresholds)))
} else {
# Nothing if no thresholds provided
""
}
}
# Otherwise, iterate over values and check contents
cell_labels <- mapply(function(md, lb, pv, lp, ld) { # mode, labels, pvalues, label p, label digits
# If matrix or data frame, make long format to replace correlation data
if (is.matrix(lb) | is.data.frame(lb)) {
lb_long <- shape_mat_long(lb)
if (is.null(cor_mat_dat)) {
cor_mat_dat <- lb_long
} else {
cor_mat_dat <- dplyr::left_join(dplyr::select(cor_mat_dat, -"value"), lb_long,
by = c("row", "col"))
}
}
# If cell_labels is not FALSE (TRUE or matrix/df) or using 'text' mode:
# use as is if p_values and cell_label_p are FALSE
# Otherwise, make matrix of values to display, taking p-values into consideration
if (!isFALSE(lb) | md == "text") {
if (!pv & !lp) {
return(lb)
} else if (!pv & lp) {
# P-values are not computed so there is nothing display
cli::cli_warn("{.var cell_label_p} is {.val TRUE} but {.var p_values} is {.val FALSE}.
Writing correlation values as no p-values have been computed.",
class = "cell_label_p_warn")
return(lb)
} else {
# If p-values are computed, either add symbols to labels or swap labels for p-values
cell_labels_long <- if (!lp) {
cor_mat_dat
} else {
dplyr::mutate(cor_mat_dat, value = p_adj)
}
cell_labels_long[["value"]] <- if (is.numeric(cell_labels_long[["value"]]) & is.numeric(ld)) {
round(cell_labels_long[["value"]], ld)
} else {
cell_labels_long[["value"]]
}
cell_labels_long <- dplyr::mutate(cell_labels_long,
# Replace NAs with "" to not get "NA" written in the cells
value = dplyr::case_when(is.na(value) ~ "", TRUE ~ as.character(value)),
value = paste0(value, p_sym))
cell_labels_wide <- shape_mat_wide(dplyr::select(cell_labels_long, row, col, value))
return(cell_labels_wide)
}
} else if (isFALSE(lb)) {
if (pv) {
# No cell labels, but p-values are computed
# Then display the p-value symbols
cell_labels_long <- cor_mat_dat
cell_labels_long[["value"]] <- p_sym
cell_labels_wide <- shape_mat_wide(dplyr::select(cell_labels_long, row, col, value))
return(cell_labels_wide)
} else {
# If just FALSE and no p-values, use as is
return(lb)
}
}
}, mode, cell_labels, p_values, cell_label_p, cell_label_digits, SIMPLIFY = FALSE)
# If only one element, unlist it
if (length(cell_labels) == 1) {cell_labels <- cell_labels[[1]]}
return(cell_labels)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.