使用“超大”矩阵绘制热力图

3

我想绘制热力图。
我有一个100k*100k的方阵(50Gb(csv),右上角填有数字,其余填0)。

我想问一下,“如何使用R在这个巨大的数据集上绘制热力图?”
我正在尝试在大内存机器上运行此代码。

d = read.table("data.csv", sep=",")
d = as.matrix(d + t(d))
heatmap(d)

我尝试了一些像heatmap.2(在gplots中)之类的库。
但它们需要太多时间和内存。


抱歉,但是一个100k x 100k瓷砖的热力图在屏幕上完全无法可视化,即使它能工作,图像也会被大大缩小,你将看到一个插值像素,而不是50x50个瓷砖...所以,为什么不先缩放矩阵,然后再调用热力图呢? - digEmAll
没错,这就是我的意思... 或者你可以将矩阵分成100个子矩阵,然后绘制每一个... - digEmAll
1
或者将其分成1000x1000矩阵并绘制平均值。 - Iaroslav Domin
@iaroslav-domin,你能把你的想法展示成代码吗?我没完全理解。 - kgyk1993
我不确定,但运行这段代码大约需要1.5小时,然后会因为内存不足(128GB)而崩溃。 - kgyk1993
显示剩余2条评论
1个回答

9
我建议您在绘制热力图之前对矩阵进行大量下采样,例如对每个子矩阵进行平均(如@IaroslavDomin所建议的)。
# example of big mx 10k x 10 k
bigMx <- matrix(rnorm(10000*10000,mean=0,sd=100),10000,10000)

# here we downsample the big matrix 10k x 10k to 100x100
# by averaging each submatrix
downSampledMx <- matrix(NA,100,100)
subMxSide <- nrow(bigMx)/nrow(downSampledMx)
for(i in 1:nrow(downSampledMx)){
  rowIdxs <- ((subMxSide*(i-1)):(subMxSide*i-1))+1
  for(j in 1:ncol(downSampledMx)){
    colIdxs <- ((subMxSide*(j-1)):(subMxSide*j-1))+1
    downSampledMx[i,j] <- mean(bigMx[rowIdxs,colIdxs])
  }
}

# NA to disable the dendrograms
heatmap(downSampledMx,Rowv=NA,Colv=NA) 

enter image description here

当然,由于您的矩阵很大,计算downSampledMx可能需要一些时间,但这是可行的。


编辑:

我认为下采样应该保留可识别的“宏观模式”,例如,看以下示例:

# create a matrix with some recognizable pattern
set.seed(123)
bigMx <- matrix(rnorm(50*50,mean=0,sd=100),50,50)
diag(bigMx) <- max(bigMx) # set maximum value on the diagonal
# set maximum value on a circle centered on the middle
for(i in 1:nrow(bigMx)){
  for(j in 1:ncol(bigMx)){
    if(abs((i - 25)^2 + (j - 25)^2 - 10^2) <= 16)
      bigMx[i,j] <- max(bigMx)
  }
}

# plot the original heatmap
heatmap(bigMx,Rowv=NA,Colv=NA, main="original")


# function used to down sample
downSample <- function(m,newSize){
  downSampledMx <- matrix(NA,newSize,newSize)
  subMxSide <- nrow(m)/nrow(downSampledMx)
  for(i in 1:nrow(downSampledMx)){
    rowIdxs <- ((subMxSide*(i-1)):(subMxSide*i-1))+1
    for(j in 1:ncol(downSampledMx)){
      colIdxs <- ((subMxSide*(j-1)):(subMxSide*j-1))+1
      downSampledMx[i,j] <- mean(m[rowIdxs,colIdxs])
    }
  }
  return(downSampledMx)
}

# downsample x 2 and plot heatmap
downSampledMx <- downSample(bigMx,25)
heatmap(downSampledMx,Rowv=NA,Colv=NA, main="downsample x 2") 

# downsample x 5 and plot heatmap
downSampledMx <- downSample(bigMx,10)
heatmap(downSampledMx,Rowv=NA,Colv=NA, main="downsample x 5") 

这是三个热力图:

enter image description here enter image description here enter image description here


谢谢@digEmAll!! 我明白了。顺便问一下,您认为降采样矩阵显示与原始矩阵相同的属性吗?我担心降采样会改变矩阵的属性(这就是为什么我尝试使用原始矩阵进行绘制)。 - kgyk1993
谢谢您的礼貌评论。当我不需要进行聚类时,我认为您所说的是正确的,但如果需要在降采样之后进行聚类,那么情况是否相似呢? - kgyk1993
@kgyk1993:嗯...下采样会“平滑”值,所以我不知道聚类结果是否相同... - digEmAll
@kgyk1993:不确定你需要什么,但也许你可以创建一个降采样的热力图,以便对值的分布有一个视觉上的了解,但在原始矩阵上执行聚类分析(我认为这里不能使用层次聚类,也许是kmeans...)。 - digEmAll
非常感谢!这个矩阵显示了大约10万条数据之间的关系得分。我想知道数据中是否存在聚类。我对此完全不了解。最后,我将矩阵降采样为十个矩阵(10k * 10k),分别进行聚类(ward.D2),并使用heatmap.2绘制(每个矩阵需要约5.5小时)。结果,有些热图看起来像是有聚类,而有些则不是,因此似乎存在聚类的可能性。 - kgyk1993

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接