具有不同颜色和尺度 R 的两个对称矩阵上的单个热图

Single heatmap on two symetric matrices with different colours and scales R

我想实现与这个问题相同的最终目标:Create a single heatmap based on two symmetric matrices in R 但比目前提供的答案更进一步。

给出的答案没有解释如何为矩阵的上部和下部使用不同的颜色和不同的比例?

这是示例数据集:

library(Matrix)
set.seed(123)

s1<-forceSymmetric(matrix(round(rnorm(25),2),5))
colnames(s1)<-LETTERS[1:5]
rownames(s1)<-LETTERS[6:10]
diag(s1)<-1

s2<-forceSymmetric(matrix(round(rbinom(25,25,0.3),2),5))
colnames(s2)<-LETTERS[1:5]
rownames(s2)<-LETTERS[6:10]
diag(s2)<-1

s1
# 5 x 5 Matrix of class "dsyMatrix"
# A     B     C     D     E
# F  1.00  1.72  1.22  1.79 -1.07
# G  1.72  1.00  0.36  0.50 -0.22
# H  1.22  0.36  1.00 -1.97 -1.03
# I  1.79  0.50 -1.97  1.00 -0.73
# J -1.07 -0.22 -1.03 -0.73  1.00

s2
# 5 x 5 Matrix of class "dsyMatrix"
# A B  C  D E
# F 1 6  8  7 9
# G 6 1  5  9 8
# H 8 5  1 10 9
# I 7 9 10  1 1
# J 9 8  9  1 1

建议的答案建议将两个矩阵加在一起:

#Get upper diagonal
reverse = s1[,ncol(s1):1]
diag(reverse) = 0
reverse[lower.tri(reverse, diag = FALSE)] <- 0
upper = reverse[,ncol(reverse):1]

# Get lower diagonal
reverse1 = s2[,ncol(s2):1]
diag(reverse1) = 0
reverse1[upper.tri(reverse1, diag = FALSE)] <- 0
upper1 = reverse1[,ncol(reverse1):1]

# Add them together
merged = as.matrix(upper+upper1)
merged
  A    B     C     D    E
F 1.00 1.72  1.22  1.79 0
G 1.72 1.00  0.36  0.00 8
H 1.22 0.36  0.00 10.00 9
I 1.79 0.00 10.00  1.00 1
J 0.00 8.00  9.00  1.00 1

然后它建议使用 heatmap(merged) - 但是,您如何为矩阵的上部和下部设置不同的颜色和比例?

我很高兴使用包括 ggplot2 在内的任何软件包来完成这项工作。

提前致谢!

您可以在图层的 data 参数中对矩阵的相关部分进行子集化,并使用 {ggnewscale} 为不同的图层分配不同的填充比例。诀窍是在添加 new_scale_fill() 之前声明填充比例,否则操作顺序会出错(这通常无关紧要,但在这里却很重要)。

然后您可以调整每个单独的比例。在下面的示例中,我只是调整了调色板,但您还可以调整限制、中断、标签等。

# Assuming code from question has been executed and we have a 'merged' in memory
library(ggplot2)
library(ggnewscale)

# Wide matrix to long dataframe
# Later, we'll be relying on the notion that the dimnames have been
# converted to factor variables to separate out the upper from the lower
# matrix.
df <- reshape2::melt(merged)


ggplot(df, aes(Var1, Var2)) +
  # The first layer, with its own fill scale
  geom_raster(
    data = ~ subset(.x, as.numeric(Var1) > as.numeric(Var2)),
    aes(fill = value)
  ) +
  scale_fill_distiller(palette = "Blues") +
  # Declare new fill scale for the second layer
  new_scale_fill() +
  geom_raster(
    data = ~ subset(.x, as.numeric(Var1) < as.numeric(Var2)),
    aes(fill = value)
  ) +
  scale_fill_distiller(palette = "Reds") +
  # I'm not sure what to do with the diagonal. Make it grey?
  new_scale_fill() +
  geom_raster(
    data = ~ subset(.x, as.numeric(Var1) == as.numeric(Var2)),
    aes(fill = value)
  ) +
  scale_fill_distiller(palette = "Greys", guide = "none")

在我看来,@teunbrand 的答案就是您要找的,但另一个可能的选择是使用 ComplexHeatmap package, e.g. based on one of the examples in the docs:

library(Matrix)
set.seed(123)

s1<-forceSymmetric(matrix(round(rnorm(25),2),5))
colnames(s1)<-LETTERS[1:5]
rownames(s1)<-LETTERS[6:10]
diag(s1)<-1

s2<-forceSymmetric(matrix(round(rbinom(25,25,0.3),2),5))
colnames(s2)<-LETTERS[1:5]
rownames(s2)<-LETTERS[6:10]
diag(s2)<-1

#Get upper diagonal
reverse = s1[,ncol(s1):1]
diag(reverse) = 0
reverse[lower.tri(reverse, diag = FALSE)] <- 0
upper = reverse[,ncol(reverse):1]

# Get lower diagonal
reverse1 = s2[,ncol(s2):1]
diag(reverse1) = 0
reverse1[upper.tri(reverse1, diag = FALSE)] <- 0
upper1 = reverse1[,ncol(reverse1):1]

# Add them together
m = as.matrix(upper+upper1)
m
#>      A    B     C     D E
#> F 1.00 1.72  1.22  1.79 0
#> G 1.72 1.00  0.36  0.00 8
#> H 1.22 0.36  0.00 10.00 9
#> I 1.79 0.00 10.00  1.00 1
#> J 0.00 8.00  9.00  1.00 1

library(ComplexHeatmap)
#> Loading required package: grid
#> ========================================
#> ComplexHeatmap version 2.8.0
#> Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
#> Github page: https://github.com/jokergoo/ComplexHeatmap
#> Documentation: http://jokergoo.github.io/ComplexHeatmap-reference
#> 
#> If you use it in published research, please cite:
#> Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
#>   genomic data. Bioinformatics 2016.
#> 
#> The new InteractiveComplexHeatmap package can directly export static 
#> complex heatmaps into an interactive Shiny app with zero effort. Have a try!
#> 
#> This message can be suppressed by:
#>   suppressPackageStartupMessages(library(ComplexHeatmap))
#> ========================================
library(circlize)
#> ========================================
#> circlize version 0.4.13
#> CRAN page: https://cran.r-project.org/package=circlize
#> Github page: https://github.com/jokergoo/circlize
#> Documentation: https://jokergoo.github.io/circlize_book/book/
#> 
#> If you use it in published research, please cite:
#> Gu, Z. circlize implements and enhances circular visualization
#>   in R. Bioinformatics 2014.
#> 
#> This message can be suppressed by:
#>   suppressPackageStartupMessages(library(circlize))
#> ========================================
col1 = colorRamp2(c(-1, 10), c("white", "red"))
col2 = colorRamp2(c(-1, 10), c("white", "blue3"))

# here reordering the symmetric matrix is necessary
od = hclust(dist(m))$order
m = m[od, od]

ht = Heatmap(m, rect_gp = gpar(type = "none"), show_heatmap_legend = FALSE,
             cluster_rows = FALSE, cluster_columns = FALSE,
             layer_fun = function(j, i, x, y, w, h, fill) {
               l = i > j
               grid.rect(x[l], y[l], w[l], h[l], 
                         gp = gpar(fill = col1(pindex(m, i[l], j[l])), col = NA))
               l = i < j
               grid.rect(x[l], y[l], w[l], h[l], 
                         gp = gpar(fill = col2(pindex(m, i[l], j[l])), col = NA))
             })
draw(ht, heatmap_legend_list = list(
  Legend(title = "Group_A", col_fun = col1),
  Legend(title = "Group_B", col_fun = col2)
))

reprex package (v2.0.1)

创建于 2022-03-07