I'm trying to create a correlation matrix represented by a heatmap with half the heatmap using colours and the other half using the actual correlation values.
So far I've been able to create two separate triangular heatmaps (one with colours and the other with correlation values). Is there a way to overlay or combine these plots in ggplot2 to create one heatmap? Is there another more efficient method to create a heatmap that's half colours and half numbers?
Here is my code below to show you what I've been doing so far.
A <- c(1,4,5,6,1)
B <- c(4,2,5,6,7)
C <- c(3,4,2,4,6)
D <- c(2,5,1,4,6)
E <- c(6,7,8,9,1)
df <- data.frame(A,B,C,D,E)
CorMat <- cor(df[ ,c("A","B","C","D","E")])
get_upper_tri <- function(CorMat){
CorMat[upper.tri(CorMat)]<- NA
return(CorMat)
}
get_lower_tri <- function(CorMat){
CorMat[lower.tri(CorMat)]<- NA
return(CorMat)
}
reorder <- function(CorMat){
dd <- as.dist((1-CorMat)/2)
hc <- hclust(dd)
CorMar <- CorMat[hc$order, hc$order]
}
CorMat <- reorder(CorMat)
upper_tri <- get_upper_tri(CorMat)
lower_tri <- get_lower_tri(CorMat)
meltNum <- melt(lower_tri, na.rm = T)
meltColor <- melt(upper_tri, na.rm = T)
ggheatmapColor <- ggplot(meltColor, aes(Var2, Var1, fill = value))
labs(x = NULL, y = NULL)
geom_tile(color = "white")
scale_x_discrete(position = "top")
scale_fill_gradient(low = "white", high = "firebrick4",
limit = c(-1,1), name = "Pearson\nCorrelation")
theme(plot.title = element_text(hjust = 0.5, face = "bold"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())
coord_fixed()
print(ggheatmapColor)
ggheatmapNum <- ggplot(meltNum, aes(Var2, Var1, label = round(value, digit = 2)))
geom_text(color = "black", size = 4)
labs(x = NULL, y = NULL)
scale_x_discrete(position = "top")
theme(plot.title = element_text(hjust = 0.5, face = "bold"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())
coord_fixed()
print(ggheatmapNum)
CodePudding user response:
I move the data and mapping from ggplot() to the geom_heatmap() and added geom_text() Perhaps this is closer to your desired result?
A <- c(1,4,5,6,1)
B <- c(4,2,5,6,7)
C <- c(3,4,2,4,6)
D <- c(2,5,1,4,6)
E <- c(6,7,8,9,1)
df <- data.frame(A,B,C,D,E)
CorMat <- cor(df[ ,c("A","B","C","D","E")])
get_upper_tri <- function(CorMat){
CorMat[upper.tri(CorMat)]<- NA
return(CorMat)
}
get_lower_tri <- function(CorMat){
CorMat[lower.tri(CorMat)]<- NA
return(CorMat)
}
reorder <- function(CorMat){
dd <- as.dist((1-CorMat)/2)
hc <- hclust(dd)
CorMar <- CorMat[hc$order, hc$order]
}
library(reshape2)
CorMat <- reorder(CorMat)
upper_tri <- get_upper_tri(CorMat)
lower_tri <- get_lower_tri(CorMat)
meltNum <- melt(lower_tri, na.rm = T)
meltColor <- melt(upper_tri, na.rm = T)
library(tidyverse)
ggplot()
labs(x = NULL, y = NULL)
geom_tile(data = meltColor,
mapping = aes(Var2, Var1,
fill = value))
geom_text(data = meltNum,
mapping = aes(Var2, Var1,
label = round(value, digit = 2)))
scale_x_discrete(position = "top")
scale_fill_gradient(low = "white", high = "firebrick4",
limit = c(-1,1), name = "Pearson\nCorrelation")
theme(plot.title = element_text(hjust = 0.5, face = "bold"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())
coord_fixed()
CodePudding user response:
To your question one - the most convenient way is to use packages that have already been created for us, for free :)
I am aware of two packages in particular, {GGally} and {ggcorrplot}. Both allow super easy creation of correlation heat maps with overlying labels.
Question 2 is probably slightly hacky and I guess Susan's answer seems reasonable.
A <- c(1,4,5,6,1)
B <- c(4,2,5,6,7)
C <- c(3,4,2,4,6)
D <- c(2,5,1,4,6)
E <- c(6,7,8,9,1)
df <- data.frame(A,B,C,D,E)
ggcorrplot::ggcorrplot(cor(df), type = "lower", lab = TRUE)
GGally::ggcorr(df, label = TRUE)
#> Registered S3 method overwritten by 'GGally':
#> method from
#> .gg ggplot2
Created on 2021-11-16 by the reprex package (v2.0.1)