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
相关产品推荐
相关产品推荐

