如何为networkx.MultiDiGraph生成对应每个样本的多维邻接矩阵
如何为networkx.MultiDiGraph生成对应每个样本的多维邻接矩阵
你已经注意到,nx.to_numpy_array对MultiDiGraph的默认行为是将同节点对的多条边权重求和,但你需要为每个sample_id单独生成一个邻接矩阵,最终拼成形状为(节点数, 节点数, 样本数)的3D数组。这里有两种实用的解决方案:
方法一:直接遍历边填充(高效推荐)
这种方法直接遍历图中所有边,根据每条边的sample_id将权重填充到3D数组的对应位置,适合节点和样本数较多的场景,执行效率更高:
import numpy as np import networkx as nx np.random.seed(123) n_samples = 10 uv = [ (1, 2), (2, 3), (3, 4), (4, 5), (5, 6) ] G = nx.MultiDiGraph() for u, v in uv: weights = np.random.uniform(0, 1, size=n_samples) G.add_edges_from([(u, v, dict(sample_id=s+1, weight=weights[s])) for s in range(n_samples)]) # 准备节点列表和索引映射,方便快速定位节点位置 nodelist = list(G.nodes) n_nodes = len(nodelist) node_to_idx = {node: idx for idx, node in enumerate(nodelist)} # 初始化全零的3D邻接矩阵 A = np.zeros((n_nodes, n_nodes, n_samples)) # 遍历所有边,按sample_id将权重填充到对应位置 for u, v, attrs in G.edges(data=True): sample_idx = attrs['sample_id'] - 1 # 转换为0-based索引适配数组 u_idx = node_to_idx[u] v_idx = node_to_idx[v] A[u_idx, v_idx, sample_idx] = attrs['weight'] # 验证数组形状 print(A.shape) # 输出: (6, 6, 10)
方法二:利用nx.to_numpy_array的自定义权重逻辑
这种方法代码更简洁,通过为每个样本自定义权重提取规则,生成单个样本的邻接矩阵后再堆叠成3D数组,可读性更强:
# 基于你已构建好的G图 nodelist = list(G.nodes) n_samples = 10 # 生成每个样本的邻接矩阵并沿最后一维堆叠 A = np.stack( [ nx.to_numpy_array( G, nodelist=nodelist, # 自定义权重规则:只保留当前sample_id的边权重,其他边权重设为0 weight=lambda u, v, d: d['weight'] if d['sample_id'] == s+1 else 0 ) for s in range(n_samples) ], axis=-1 ) print(A.shape) # 输出: (6, 6, 10)
结果验证
你可以通过切片查看单个样本的邻接矩阵,比如查看第一个样本(对应sample_id=1)的矩阵:
print(A[:, :, 0])
这会输出仅包含对应样本边权重的邻接矩阵,完全避免了权重求和的默认行为,符合你的需求。
备注:内容来源于stack exchange,提问作者HJA24




