NetworkX subgraph边顺序异常,求同功能正确排序的内置函数
问题
在使用NetworkX的MultiGraph时,调用G.subgraph(path)生成子图后,返回的边顺序不符合预期,导致nx.get_edge_attributes(subgraph)获取的属性顺序错误。需要找到一种类似subgraph的方法,能保证边的顺序符合需求。
相关代码示例(已修正原代码中变量定义顺序错误):
import networkx as nx import matplotlib.pyplot as plt relations = [ ('x3', 'x100', 'friend'),('x1', 'x2', 'friend'), ('x4', 'x12200', 'friend'),('x3', 'x2', 'friend'),('P20', 'P3', 'friend'),('x4', 'x3', 'friend'),('x4', 'x5', 'friend'),('x1', 'x0', 'friend'),('P1', 'P2', 'friend'),('P1', 'P0', 'friend'), ('P4', 'P5', 'friend'), ('A', 'B', 'friend'), ('B', 'C', 'coworker'), ('C', 'F', 'coworker'), ('C', 'F', 'friend'), ('F', 'G', 'coworker'), ('F1', 'F2', 'coworker'),('F3', 'F2', 'friend'), ('F3', 'F4', 'friend'),('F6', 'F4', 'friend'), ('F5', 'F6', 'coworker'),('F6', 'F1', 'coworker'), ('F', 'G', 'family'), ('C', 'lo', 'friend'), ('E', 'lo', 'friend'),('E', 'D', 'family'),('J', 'D', 'family'), ('E', 'I', 'coworker'), ('E', 'I', 'neighbour'), ('I', 'J', 'coworker'),('P3', 'P2', 'friend'), ('E', 'J', 'friend'), ('P5', 'P6', 'coworker'),('P7', 'P6', 'coworker'),('E', 'H', 'coworker'),('V', 'L', 'friend'),('M', 'L', 'friend'),('M', 'N', 'friend'), ('N', 'O', 'coworker'),('N', 'P', 'friend'), ('L', 'N', 'coworker')] G = nx.MultiGraph() for i in relations: G.add_edge(i[0], i[1], relation = i[2]) path = list(nx.dfs_preorder_nodes(G, source="P0")) print("path", path) print(G.subgraph(path).edges()) attribute = nx.get_edge_attributes((G.subgraph(path)), "relation") print("attribute", attribute.values())
当前输出:
path ['P0', 'P1', 'P2', 'P3', 'P20'] [('P1', 'P2'), ('P1', 'P0'), ('P2', 'P3'), ('P20', 'P3')] ['friend', 'friend', 'hey', 'friend', 'friend']
期望输出:
path ['P0', 'P1', 'P2', 'P3', 'P20'] [('P0', 'P1'), ('P1', 'P2'), ('P2', 'P3'), ('P20', 'P3')] # 注:边内节点顺序无需严格一致 ['friend', 'friend', 'friend', 'friend', 'hey']
对应图结构:
解决方案
NetworkX的图(包括MultiGraph)本质是无序结构,subgraph()方法仅提取指定节点的关联边,但不会保留任何特定顺序,因此不存在直接满足需求的内置subgraph变体。解决的核心是主动控制边的添加顺序,具体实现如下:
实现步骤
- 用
nx.dfs_edges()获取DFS遍历过程中访问的边,这部分边的顺序与DFS节点遍历顺序一致。 - 补充path中剩余节点间的关联边(比如示例中P20与P3的边)。
- 手动按指定顺序构建子图,确保边的顺序符合预期,同时完整复制边属性。
修正后的代码
import networkx as nx relations = [ ('x3', 'x100', 'friend'),('x1', 'x2', 'friend'), ('x4', 'x12200', 'friend'),('x3', 'x2', 'friend'),('P20', 'P3', 'friend'),('x4', 'x3', 'friend'),('x4', 'x5', 'friend'),('x1', 'x0', 'friend'),('P1', 'P2', 'friend'),('P1', 'P0', 'friend'), ('P4', 'P5', 'friend'), ('A', 'B', 'friend'), ('B', 'C', 'coworker'), ('C', 'F', 'coworker'), ('C', 'F', 'friend'), ('F', 'G', 'coworker'), ('F1', 'F2', 'coworker'),('F3', 'F2', 'friend'), ('F3', 'F4', 'friend'),('F6', 'F4', 'friend'), ('F5', 'F6', 'coworker'),('F6', 'F1', 'coworker'), ('F', 'G', 'family'), ('C', 'lo', 'friend'), ('E', 'lo', 'friend'),('E', 'D', 'family'),('J', 'D', 'family'), ('E', 'I', 'coworker'), ('E', 'I', 'neighbour'), ('I', 'J', 'coworker'),('P3', 'P2', 'friend'), ('E', 'J', 'friend'), ('P5', 'P6', 'coworker'),('P7', 'P6', 'coworker'),('E', 'H', 'coworker'),('V', 'L', 'friend'),('M', 'L', 'friend'),('M', 'N', 'friend'), ('N', 'O', 'coworker'),('N', 'P', 'friend'), ('L', 'N', 'coworker')] G = nx.MultiGraph() for i in relations: G.add_edge(i[0], i[1], relation=i[2]) # 获取DFS遍历的节点路径和边 path = list(nx.dfs_preorder_nodes(G, source="P0")) dfs_edges = list(nx.dfs_edges(G, source="P0")) # 收集子图需要的所有边:先保留DFS遍历的边,再补充剩余节点间的边 sub_edges = dfs_edges.copy() node_set = set(path) # 遍历所有节点对,避免重复添加边 added_edges = set((min(u,v), max(u,v)) for u,v in dfs_edges) for u in path: for v in G.neighbors(u): if v in node_set: edge_key = (min(u,v), max(u,v)) if edge_key not in added_edges: sub_edges.append((u, v)) added_edges.add(edge_key) # 按顺序构建子图,复制所有边属性 subgraph = nx.MultiGraph() for u, v in sub_edges: # 遍历MultiGraph中u-v之间的所有边,复制属性 for key, attrs in G[u][v].items(): subgraph.add_edge(u, v, **attrs) # 输出结果 print("path", path) print("subgraph edges:", list(subgraph.edges())) attribute_values = list(nx.get_edge_attributes(subgraph, "relation").values()) print("attribute values:", attribute_values)
关键说明
nx.dfs_edges()返回的边顺序完全匹配DFS节点的遍历顺序,解决了核心的边顺序需求。- 手动构建子图时,严格按照自定义顺序添加边,后续获取属性时顺序自然与边的顺序一致。
- 针对MultiGraph的特性,遍历每条边的key和属性,确保所有关联边都被完整复制,避免遗漏。
内容的提问来源于stack exchange,提问作者cynthia
相关产品推荐
相关产品推荐

