在R中对距离矩阵做中心对数比变换后为何不对称?
解决CLR变换后距离矩阵不对称的问题
问题根源
- CLR变换的行计算特性:
compositions::clr()默认按行执行变换,每行的几何均值是该行所有元素的平均对数的指数。即使原矩阵中dm[i,j] = dm[j,i],但这两个值分别属于第i行和第j行,计算时使用的几何均值不同,最终变换结果自然不同,破坏了矩阵对称性。 - 距离矩阵的0值问题:距离矩阵的对角线为0,而CLR变换要求所有输入值必须为正数(因为涉及对数运算),0值的存在本身就不符合CLR的应用前提。
解决方法
我们需要同时处理0值,并保证变换时对称位置的元素使用相同的参考基准,从而维持矩阵对称性。以下是两种可行方案:
方案1:基于全局几何均值的CLR变换
对整个矩阵的非对角线元素计算全局几何均值,以此为基准进行CLR变换,确保所有对称位置的元素使用同一参考值:
library(compositions) # 加载你的距离矩阵 dm <- structure(list(X1 = c(0, 0.2177609998, 0.2133361674, 0.1549136105, 0.1400395799), X11 = c(0.2177609998, 0, 0.07805820645, 0.1418994689, 0.1934668819), X12 = c(0.2133361674, 0.07805820645, 0, 0.1475390242, 0.1857477705), X13 = c(0.1549136105, 0.1418994689, 0.1475390242, 0, 0.1046740994), X14 = c(0.1400395799, 0.1934668819, 0.1857477705, 0.1046740994, 0)), row.names = c("X1", "X11", "X12", "X13", "X14" ), class = "data.frame") dm_matrix <- as.matrix(dm) # 1. 处理0值:添加极小偏移量避免对数错误 dm_nonzero <- dm_matrix + 1e-8 # 2. 计算全局几何均值(仅使用非对角线元素) global_gmean <- exp(mean(log(dm_nonzero[upper.tri(dm_nonzero)]))) # 3. 执行全局CLR变换 dm_clr_global <- log(dm_nonzero / global_gmean) # 验证对称性 isSymmetric(dm_clr_global)
方案2:利用矩阵对称性,仅处理三角区域
由于原矩阵是对称的,我们可以只提取上三角(或下三角)的非对角线元素进行CLR变换,再将结果复制到对称位置,确保矩阵对称:
library(compositions) # 加载并转换矩阵 dm <- structure(list(X1 = c(0, 0.2177609998, 0.2133361674, 0.1549136105, 0.1400395799), X11 = c(0.2177609998, 0, 0.07805820645, 0.1418994689, 0.1934668819), X12 = c(0.2133361674, 0.07805820645, 0, 0.1475390242, 0.1857477705), X13 = c(0.1549136105, 0.1418994689, 0.1475390242, 0, 0.1046740994), X14 = c(0.1400395799, 0.1934668819, 0.1857477705, 0.1046740994, 0)), row.names = c("X1", "X11", "X12", "X13", "X14" ), class = "data.frame") dm_matrix <- as.matrix(dm) # 1. 处理0值 dm_nonzero <- dm_matrix + 1e-8 # 2. 提取上三角非对角线元素并做CLR变换 upper_vals <- dm_nonzero[upper.tri(dm_nonzero)] upper_clr <- clr(upper_vals) # 3. 构建对称变换矩阵 dm_clr_sym <- matrix(0, nrow = nrow(dm_matrix), ncol = ncol(dm_matrix)) dm_clr_sym[upper.tri(dm_clr_sym)] <- upper_clr # 复制上三角结果到下三角,保证对称 dm_clr_sym[lower.tri(dm_clr_sym)] <- t(dm_clr_sym)[lower.tri(dm_clr_sym)] # 验证对称性 isSymmetric(dm_clr_sym)
关键说明
- 不要直接对距离矩阵按行执行CLR变换,这会破坏矩阵的对称性。
- 必须先处理距离矩阵中的0值,否则会导致对数运算错误或变换结果异常。
内容的提问来源于stack exchange,提问作者shannonevelyne
相关产品推荐
相关产品推荐

