#' Heatmap Plot (Upper Triangle) #' #' Minimal ggplot2 relationship structure plot showing the upper triangle #' in the top-right corner with no axis labels. #' @param R A square numeric correlation matrix #' @param title Optional plot title #' @param labels Logical to plot column names or not (default FALSE) #' @param order Optional character vector of the order you want the plot sorted in #' #' @return A ggplot object #' #' @examples #' X <- matrix(data = rnorm(100), nrow = 10) #' R <- cor(X) #' heatmap(R, title = 'Example Correlation Plot') #' #' @importFrom reshape2 melt #' @import ggplot2 #' @export heatmap <- function(R, title = NULL, labels = FALSE, order = NULL){ R_list <- tryCatch({ if(is.matrix(R)){ Rm <- R }else{ Rm <- as.matrix(R) } if(nrow(Rm) != ncol(Rm)){ stop('Input must be coercible to a square matrix') } cnames <- colnames(Rm) rnames <- rownames(Rm) if(is.null(cnames)){ cnames <- as.character(seq_len(ncol(Rm))) } if(is.null(rnames)){ rnames <- as.character(seq_len(nrow(Rm))) } if(!is.null(order)){ if(length(order) != nrow(Rm)){ stop('Provided order is not the same length as the width of R') }else{ rownames(Rm) <- rnames colnames(Rm) <- cnames Rm <- Rm[order, order, drop = FALSE] } } list( cnames = colnames(Rm), rnames = rownames(Rm), R = Rm[upper.tri(Rm)], p = ncol(Rm) ) }, error = function(e){ stop(paste('Invalid input for heatmap:', e$message)) }) # Now get a df from the upper triangle n <- R_list$p M <- matrix(NA, n, n) M[upper.tri(M)] <- R_list$R colnames(M) <- R_list$cnames rownames(M) <- R_list$rnames df <- reshape2::melt(M, na.rm = TRUE) names(df) <- c('i', 'j', 'value') df$i <- match(df$i, rownames(M)) df$j <- match(df$j, colnames(M)) # And plot it p <- ggplot2::ggplot( data = df, ggplot2::aes(x = .data$j, y = .data$i, fill = .data$value) ) + ggplot2::geom_tile() + ggplot2::scale_y_reverse() + ggplot2::coord_fixed(clip = 'off') + ggplot2::scale_fill_gradient2( low = 'red', mid = 'white', high = 'blue', midpoint = 0, limits = c(-1, 1), name = NULL, guide = 'none' ) + ggplot2::theme_void() if(!is.null(title)){ p <- p + ggplot2::ggtitle(title) + ggplot2::theme( plot.title = ggplot2::element_text(hjust = 0.5) ) } if(labels){ col_label_df <- data.frame( j = seq_len(n)[-1], i = 0, label = R_list$cnames[-1] ) row_label_df <- data.frame( j = seq_len(n)[-n], i = seq_len(n)[-n], label = R_list$rnames[-n] ) max_nchar <- max(nchar(R_list$cnames)) top_margin <- 5 + max_nchar * 2 p <- p + ggplot2::geom_text( data = col_label_df, ggplot2::aes(x = .data$j, y = .data$i, label = .data$label), inherit.aes = FALSE, angle = 90, hjust = 0, vjust = 0.5 ) + ggplot2::geom_text( data = row_label_df, ggplot2::aes(x = .data$j, y = .data$i, label = .data$label), inherit.aes = FALSE, hjust = 1, vjust = 0.5 ) + ggplot2::theme( plot.margin = ggplot2::margin( t = top_margin, r = 5, b = 5, l = 5 ) ) } return(p) }