首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从单个矩阵创建多个单独的热图

从单个矩阵创建多个单独的热图
EN

Stack Overflow用户
提问于 2012-10-27 00:19:51
回答 3查看 3.7K关注 0票数 1

我想要将一个42x42矩阵可视化为28个单独的热图,每个热图是6x6矩阵,值绘制在颜色的顶部。我只需要矩阵的下半部分,我不想画出任何被排除的东西。后续的6x6矩阵不能重叠,如下例所示:

代码语言:javascript
运行
复制
d = as.matrix(read.table("http://dl.dropbox.com/u/2505196/matrix_posthoc_tukey.dat"))
d[upper.tri(d)] <- NA
d1 <- d[1:6, 1:6]
d2 <- d[1:6, 7:12]
d3 <- d[1:6, 13:18]
d4 <- d[1:6, 18:24]
#...etc, up to d28 <- d[37:42,37:42] 

我用来创建单个热图的代码如下所示:

代码语言:javascript
运行
复制
#baseline to create a separated space for all 28 plots
par(mfrow=c(4,7), mar=c(2,2,4,1), oma=c(2,4,2,2))

#using `image` to create heatmap, with color breaks defined by specific values
#the code below create just single heatmap
image(x=1:6, y=1:6, axes = FALSE, ylab="", xlab="", d1, 
  breaks=c(min(d1,na.rm=TRUE), -5.45, -4.65, 4.65, 5.45, max(d1,na.rm=TRUE)),
  col=c("red","orange","white","orange","red"))
axis(2, 1:6, cex.axis = 0.7, las=1, tick=F)
axis(3, 1:6, cex.axis = 0.7, tick=F)
#create vertical and forizontal lines
abline(h=seq(0.5,6.5,1), v=seq(0.5,6.5,1))
#plot values from the specific matrix subset
for (i in 1:6)
   {
     for (j in 1:6)
       {
         txt <- sprintf("%0.1f", d1[i,j])
         text(i, j, txt, cex=0.7)
        }
   }

三个这样的热图如下所示:

这就是我被困住的地方。每次向我的单页多热图集合中添加另一个图像时,我都必须手动更改d的值。我不知道如何使用上面的代码创建一个很好的循环来同时绘制矩阵的这些特定子集。

使用ggplot2、晶格的替代解决方案也很受欢迎,尽管我相信这里的主要问题是制作这一系列热图的一个很好的循环。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-10-29 16:29:03

这是一个相当复杂的图,但它可以很容易地由R中的标准图形库生成。它或多或少只是跟踪哪些索引进入哪个面板的问题。可以自动提取d28d28矩阵的方法,这样就不必写出每一行。

代码语言:javascript
运行
复制
# Get the submatrices
I <- unlist(lapply(0:6, function(a) a:6))
J <- rep(0:6, 7:1)
d2 <- mapply(function(i,j) d[1:6+6*i, 1:6+6*j], I, J, SIMPLIFY=FALSE)

# Setup the layout and add an outer margin for the title and axis labels
layout(matrix(c(1:28, 0, 0), 5, 6))
par(oma=c(3,3,3,1), mar=c(2,2,1,1))

# Plot all the matrices oriented the same way they appear in text
# i.e. the first (vertical) dimension is plotted along the Y-axis
for(k in 1:length(d2)){
    x <- 1:6+6*J[k]
    y <- 1:6+6*I[k]

    # Heatmap & grid
    image(x, y, t(d2[[k]][nrow(d2[[k]]):1,]), las=1, axes=FALSE,
          breaks=c(-1e10, -5.45, -4.65, 4.65, 5.45, 1e10),
          col=c("red","orange","white","orange","red"))
    xg <- apply(!is.na(d2[[k]]), 2, sum)
    yg <- rev(apply(!is.na(d2[[k]]), 1, sum))
    segments(c(x[1]-1, x)+.5, min(y)-.5,
             c(x[1]-1, x)+.5, min(y)+c(6, yg)-.5, xpd=TRUE)
    segments(min(x)-.5,         c(y[1]-1, y)+.5,
             min(x)+c(6,xg)-.5, c(y[1]-1, y)+.5, xpd=TRUE)

    # X & Y-axis values
    mtext(x, 1, .1, at=x, cex=.5)
    mtext(rev(y), 2, .2, at=y, las=1, cex=.5)

    # Values of each cell
    text(rep(x, each=6), rep(rev(y), 6),
     sub("NA", "", sprintf("%.2f", d2[[k]])), cex=.3)
}

# Add title and axis labels
title("All 28 submatrices", outer=TRUE)
mtext("Columns", outer=TRUE, 1, 1)
mtext("Rows", outer=TRUE, 2, 1)

每个单元格中的数字可能很小,但如果您将其绘制为pdf并放大,则可以读取它们。segments函数的xpd参数禁止R将线条裁剪到绘图区(否则,外部线条会稍微变细)。

票数 3
EN

Stack Overflow用户

发布于 2012-10-27 08:19:08

要获得原始矩阵的6x6子数组,您可以执行以下操作:

代码语言:javascript
运行
复制
for (i in seq(1, 42, 6))
    for (j in seq(i, 42, 6)) {
        dsub = d[i:(i+5), j:(j+5)]
        ...
    }

然而,我建议使用一种更好的方法来创建热图-而不是重新发明它。虽然我最喜欢的制作普通热图的软件包是pheatmap (= pretty heatmap),但它不支持在同一页面中有多个小热图。这只是一个pheatmap()输出的示例,在安装并加载软件包后,您可以通过运行?pheatmap来查看该函数的帮助。

要在同一页中包含多个热图,您可以使用ggplot2包。这里有一些很好的how to make ggplot2 heatmapshaving multiple plots on the same page.手册

票数 1
EN

Stack Overflow用户

发布于 2012-10-27 04:33:28

我认为你只需要一个嵌套循环,并且你的d#必须是一个数组(我称之为subs表示子矩阵)。请原谅我的代码,因为我并不真正了解R,但类似于:

代码语言:javascript
运行
复制
for (row in 1:7)
  {
    for (col in 1:7)
      {
        subs[((row-1)*6)+j] <- d[ ((row-1)*6) + 1) : (row*6), (((col-1)*6) + 1) : (col*6)] 
      }
  }

这将为您提供全部49个子矩阵。如果你只想要前4列的子矩阵,你可以在循环中选择1:4的范围。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13090675

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档