如何将相关矩阵转换为边列表,用于构建带显著性判断的加权网络图?
解决igraph中从相关矩阵生成带显著性边列表的问题
我明白你现在卡在从相关矩阵转成符合要求的边列表这一步了——既要保留显著相关的边,又要把相关系数作为权重,用igraph的时候还拿不到相关性的关键信息,确实挺头疼的。咱们一步步来拆解这个问题:
第一步:先搞定相关系数和显著性检验的结果
首先你得先把相关系数矩阵和对应的显著性p值矩阵都算出来,igraph本身不负责统计检验,所以得先用统计工具(比如scipy或者pingouin)先把这俩矩阵拿到手。举个用scipy的例子:
import numpy as np import pandas as pd from scipy.stats import pearsonr # 假设你的数据是df,每行是样本,每列是节点(变量) df = pd.DataFrame(np.random.randn(100, 5), columns=["A", "B", "C", "D", "E"]) # 初始化相关系数和p值矩阵 corr_matrix = pd.DataFrame(np.eye(df.shape[1]), index=df.columns, columns=df.columns) pval_matrix = pd.DataFrame(np.eye(df.shape[1]), index=df.columns, columns=df.columns) # 遍历所有变量对计算相关和p值 for i in range(df.shape[1]): for j in range(i+1, df.shape[1]): corr, pval = pearsonr(df.iloc[:, i], df.iloc[:, j]) corr_matrix.iloc[i, j] = corr corr_matrix.iloc[j, i] = corr pval_matrix.iloc[i, j] = pval pval_matrix.iloc[j, i] = pval
第二步:把矩阵转成符合要求的边列表
接下来要把矩阵里的信息转成边列表,只保留**p值小于显著性水平(比如0.05)**的边,同时带上相关系数作为权重。这里可以用pandas的stack()方法快速处理:
# 把相关矩阵转成长格式,去掉对角线(自己和自己的连接) edges_corr = corr_matrix.stack().reset_index() edges_corr.columns = ["source", "target", "weight"] # 把p值矩阵也转成长格式 edges_pval = pval_matrix.stack().reset_index() edges_pval.columns = ["source", "target", "p_value"] # 合并两个表,然后筛选显著的边,并且去掉重复的边(因为A-B和B-A是同一条边) edges_combined = pd.merge(edges_corr, edges_pval, on=["source", "target"]) edges_combined = edges_combined[edges_combined["source"] < edges_combined["target"]] # 避免重复 edges_significant = edges_combined[edges_combined["p_value"] < 0.05] # 筛选显著边
第三步:导入igraph并保留相关性信息
现在这个edges_significant就是符合要求的边列表了,直接导入igraph,而且权重和p值都能作为边的属性保留下来:
import igraph as ig # 创建图对象 g = ig.Graph.DataFrame(edges_significant, directed=False) # 检查边的属性——你现在就能拿到权重和p值了 for edge in g.es: print(f"边 {g.vs[edge.source]['name']}-{g.vs[edge.target]['name']}: 相关系数={edge['weight']}, p值={edge['p_value']}")
关键提醒
- 如果你一开始直接用igraph从相关矩阵生成图,它只会把矩阵值当成权重,但不会帮你做显著性筛选,也不会保留p值这类统计信息——所以必须先在外部完成统计检验和筛选,再把处理好的边列表喂给igraph。
- 要是你的变量很多,遍历所有对可能有点慢,可以用
pingouin的corr()方法直接生成包含p值的长格式结果,能省不少代码:
import pingouin as pg corr_results = pg.pairwise_corr(df, method="pearson") edges_significant = corr_results[corr_results["p-corr"] < 0.05][["X", "Y", "r", "p-corr"]] edges_significant.columns = ["source", "target", "weight", "p_value"]
这样操作下来,你就能得到一个只包含显著相关边、且每条边都带有相关系数权重的网络图,而且所有相关性的统计信息都能在igraph里访问到啦。
内容的提问来源于stack exchange,提问作者herbert
相关产品推荐
相关产品推荐

