微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从过滤边的 subgraph_view 获取 networkx 过滤节点

如何解决从过滤边的 subgraph_view 获取 networkx 过滤节点

我通过对边应用过滤器创建了一个 subgraph_view。当我在子图上调用 nodes() 时,它仍然向我显示所有节点,即使没有任何边使用它们。我需要获取仅包含仍属于子图一部分的节点的列表。

G = nx.path_graph(6)
G[2][3]["cross_me"] = False
G[3][4]["cross_me"] = False
def filter_edge(n1,n2):
    return G[n1][n2].get("cross_me",True)
view = nx.subgraph_view(G,filter_edge=filter_edge)
# node 3 is no longer used by any edges in the subgraph
view.edges()

这会产生

EdgeView([(0,1),(1,2),(4,5)])

正如预期的那样。但是,当我运行 view.nodes() 时,我得到

NodeView((0,1,2,3,4,5))

我希望看到的是

NodeView((0,5))

这看起来很奇怪。有没有办法只提取子图使用的节点?

解决方法

混淆源于“图形”的定义。断开连接的节点仍然是图形的一部分。事实上,您可以有一个 graph with no edges at all。所以 subgraph_view() 的行为违反直觉但正确。

但是,如果您仍然想要实现您所描述的内容,则有很多潜在的方法,具体取决于您对修改原始图形的容忍度。我将提到两个尝试尽可能接近您当前的方法并避免 G 中的 deleting edges or nodes

方法一

使用 view 对象的最简单方法是将其作为 edge_subgraph() 的输入(仅将边作为输入),如下所示:

final_view = view.edge_subgraph(view.edges())
final_view.nodes()

给予

NodeView((0,1,2,4,5))

方法二

对我来说,通过定义一个中间视图,方法 1 显得笨拙和混乱。相反,如果我们返回一点点并从 G 开始,我们可以定义一个 filter_node 函数来检查每个节点的边缘属性并过滤该节点如果

  1. 所有边缘都标记为移除,或
  2. 该节点首先没有边。

您也可以通过手动标记节点本身来做到这一点,就像您对边所做的那样。

G = nx.path_graph(6)
G[2][3]["cross_me"] = False
G[3][4]["cross_me"] = False
def filter_edge(n1,n2):
    return G[n1][n2].get("cross_me",True)
def filter_node(n):
    return sum([i[2].get("cross_me",True) for i in G.edges(n,data=True)])
view = nx.subgraph_view(G,filter_node=filter_node,filter_edge=filter_edge)

view.nodes()

也给出了预期

NodeView((0,5))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。