网络图(networkx)仅有一个名为
Graph.subgraph()
的函数用于创建由节点诱导出的子图。 但是如何从边列表构建子图呢?
谢谢!
如果您有一组边的列表,那么您已经拥有了子图。只需在该列表上调用nx.Graph
,并可以选择添加原始图中未连接的节点。从文档中获取更多信息。
Graph.__init__(data=None, **attr)
Graph.subgraph()
在从节点创建的子图中所具有的属性的函数,但是这个函数是在边缘迭代器上工作的,那么您需要保留对原始图形、边缘和节点的引用,以便能够传播图形、边缘或节点数据属性的更改。特别是从Graph.subgraph()
的docstring中可以看出:
目前提议的方法将不会反映其属性在原始图中的更改,因为它们将从头开始创建一个新的图形。图形、边缘或节点属性只是指向原始图形。因此,对节点或边缘结构的更改不会反映在原始图形中,而对属性的更改则会。
要创建一个具有其自己的边/节点属性副本的子图,请使用: nx.Graph(G.subgraph(nbunch))
如果边缘属性是容器,则可以使用以下方式获得深度拷贝:G.subgraph(nbunch).copy()
.subgraph
的基础设施,因此应该适用于Graph和DiGraph。它不适用于MultiGraph和MultiDiGraph,因为MultiGraph和MultiDiGraph可能需要引用边缘的键,而当前的方法忽略了第二个参数之后的参数,因此不考虑传递的边缘列表是否附带字典属性。即使它是在没有引用的情况下创建的(通过传递ref_back=False
),它也不会使用nx.Graph
或nx.DiGraph
类初始化程序创建一个新图形,而是对原始图形进行深度拷贝。可以扩展它以涵盖其他情况...但是我现在不需要这样做,直到有人明确要求为止,我将假定没有其他人需要它(如果您想查看我在实践中使用的版本,请参见github)。def subgraph_from_edges(G,edge_list,ref_back=True):
"""
Creates a networkx graph that is a subgraph of G
defined by the list of edges in edge_list.
Requires G to be a networkx Graph or DiGraph
edge_list is a list of edges in either (u,v) or (u,v,d) form
where u and v are nodes comprising an edge,
and d would be a dictionary of edge attributes
ref_back determines whether the created subgraph refers to back
to the original graph and therefore changes to the subgraph's
attributes also affect the original graph, or if it is to create a
new copy of the original graph.
"""
sub_nodes = list({y for x in edge_list for y in x[0:2]})
edge_list_no_data = [edge[0:2] for edge in edge_list]
assert all([e in G.edges() for e in edge_list_no_data])
if ref_back:
G_sub = G.subgraph(sub_nodes)
for edge in G_sub.edges():
if edge not in edge_list_no_data:
G_sub.remove_edge(*edge)
else:
G_sub = G.subgraph(sub_nodes).copy()
for edge in G_sub.edges():
if edge not in edge_list_no_data:
G_sub.remove_edge(*edge)
return G_sub
edge_list_no_data = [edge[0:2] for edge in edge_list]
,并且for edge in G_sub.edges():
需要更改为类似于for edge in G_sub.edges(keys=True):
的内容,但是然后您需要确保edge_list_no_data
确实具有其他行所需的键。 - mpacer@larsmans的答案是正确的。这里是一个简单的例子:
In [1]: import networkx as nx
In [2]: G = nx.path_graph(6)
In [3]: G.edges()
Out[3]: [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
In [4]: subgraph_edges = [(1,2), (3,4)]
In [5]: S = nx.Graph(subgraph_edges)
In [6]: S.edges()
Out[6]: [(1, 2), (3, 4)]
nx.edge_subgraph
的函数来实现此功能。它保留了原始图形的属性,但对这些属性的更改将反映在原始图形中。G = nx.path_graph(5)
S = G.edge_subgraph([(0, 1), (3, 4)])
list(S.nodes) # [0, 1, 3, 4]
list(H.edges) # [(0, 1), (3, 4)]
FG = nx.Graph(fedges)
G = G.subgraph(FG.nodes())
这里,fedges 是构建子图的筛选边的列表。首先,使用筛选后的边创建一个新的临时图(FG)。然后使用节点列表(FG.nodes())从原图中获取一个子图。由于你实际上是在原始图对象上使用 subgraph 函数,因此不会失去任何属性。
nx.Graph
G
的原始图)G.subgraph(nbunch).copy()
(请参见https://networkx.readthedocs.org/en/latest/reference/generated/networkx.Graph.subgraph.html#networkx.Graph.subgraph)。如果您想以保留引用的方式执行此操作,我认为您需要采用不同的方法。我可能需要这样做,如果我解决了它,我会发布一个答案。 - mpacer