You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

vegdist生成的相似性热图对角线值错误问题排查与解决

问题

我想要评估若干含基因名的向量间的相似性,仅拥有基因名数据,因此计划使用Jaccard相异度转换为相似性后绘制热图。示例代码如下:

library(vegan)
library(pheatmap)

data <- matrix(c(1, 0, 1,
                 1, 1, 0,
                 0, 1, 1,
                 1, 1, 1),
               ncol = 3, byrow = TRUE)

rownames(data) <- c("Gene1", "Gene2", "Gene3", "Gene4")
colnames(data) <- c("Sample1", "Sample2", "Sample3")
dissimilarity <- vegdist(data, method = "jaccard")
similarity <- 1 - dissimilarity

pheatmap(as.matrix(dissimilarity), main = "Jaccard Dissimilarity")
pheatmap(as.matrix(similarity), main = "Jaccard Similarity")                   

heatmap(as.matrix(similarity), main = "Jaccard Similarity")
heatmap(as.matrix(dissimilarity), main = "Jaccard Dissimilarity")

相异度热图的对角线值为0,符合样本自身距离为0的预期;但转换为相似性后,预期对角线值应为1(1-0=1),实际热图中对角线仍为0。我推测是vegdist生成的矩阵存在空值,被heatmap和pheatmap自动填充为0,但不确定如何在不手动修改矩阵的情况下修复。请问我的相似性计算方式是否有误?如何在不手动修改矩阵的前提下修正对角线值与对应颜色?

解决方案

问题根源

你的相似性计算方式没有错误。问题出在vegdist生成的是dist类距离对象,这类对象仅存储非对角线的距离值,对角线的自身距离默认不存储(理论上相异度为0)。当你将1 - dissimilarity得到的相似性dist对象转换为矩阵时,系统会自动将对角线填充为0,而非预期的1。

修正方案(无需手动逐个修改值)

可以通过一行代码自动修正矩阵的对角线值,同时保留原有计算逻辑:

library(vegan)
library(pheatmap)

data <- matrix(c(1, 0, 1,
                 1, 1, 0,
                 0, 1, 1,
                 1, 1, 1),
               ncol = 3, byrow = TRUE)

rownames(data) <- c("Gene1", "Gene2", "Gene3", "Gene4")
colnames(data) <- c("Sample1", "Sample2", "Sample3")

dissimilarity <- vegdist(data, method = "jaccard")
similarity <- 1 - dissimilarity

# 转换为矩阵并自动设置对角线为1
sim_matrix <- as.matrix(similarity)
diag(sim_matrix) <- 1

# 绘制修正后的相似性热图
pheatmap(sim_matrix, main = "Jaccard Similarity (Corrected)")
heatmap(sim_matrix, main = "Jaccard Similarity (Corrected)")

# 相异度热图保持原有逻辑即可
pheatmap(as.matrix(dissimilarity), main = "Jaccard Dissimilarity")
heatmap(as.matrix(dissimilarity), main = "Jaccard Dissimilarity")

替代方案:直接计算Jaccard相似性矩阵

如果想跳过dist对象的限制,直接生成带有正确对角线值的相似性矩阵,可以自定义函数实现:

# 自定义Jaccard相似性计算函数
jaccard_sim <- function(x) {
  mat <- matrix(0, nrow = nrow(x), ncol = nrow(x))
  rownames(mat) <- rownames(x)
  colnames(mat) <- rownames(x)
  
  for (i in 1:nrow(x)) {
    for (j in 1:nrow(x)) {
      intersect_count <- sum(x[i,] & x[j,])
      union_count <- sum(x[i,] | x[j,])
      mat[i,j] <- intersect_count / union_count
    }
  }
  return(mat)
}

# 直接生成相似性矩阵
sim_matrix_direct <- jaccard_sim(data)
# 绘制热图
pheatmap(sim_matrix_direct, main = "Direct Jaccard Similarity")
heatmap(sim_matrix_direct, main = "Direct Jaccard Similarity")

这种方式生成的矩阵天然带有对角线值1,无需额外修正。

内容的提问来源于stack exchange,提问作者danvoronov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:32:08