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, 1, 2, 4, 5))
这似乎很奇怪。有没有办法只提取子图使用的节点?
解决方案
混淆源于“图形”的定义。断开连接的节点仍然是图的一部分。事实上,你可以有一个完全没有边的图。所以 的行为subgraph_view()
是违反直觉但正确的。
但是,如果您仍想实现所描述的内容,则有很多潜在的方法,具体取决于您对修改原始图形的容忍度。我将提到两个尝试尽可能接近您当前方法并避免从G
.
方法一
使用view
对象的最简单方法是将其作为输入edge_subgraph()
(仅将边作为输入),如下所示:
final_view = view.edge_subgraph(view.edges())
final_view.nodes()
给
NodeView((0, 1, 2, 4, 5))
方法二
对我来说,通过定义中间视图,方法 1 显得笨拙且令人困惑。相反,如果我们返回一点并从 开始G
,我们可以定义一个filter_node
函数来检查每个节点的边缘属性并过滤该节点,如果
- 所有边缘都被标记为删除,或者
- 该节点首先没有边。
您也可以通过手动标记节点本身来做到这一点,就像您对边缘所做的那样。
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, 1, 2, 4, 5))
推荐阅读
- firebird - 如何为给定的数据类型获取更高和更低的值?
- php - 连接 PHP 和 HTML
- mongodb - 猫鼬排序不能用作查找选项
- git - 如何将主代码添加到开发分支
- azure - ping 类在已发布的网络核心 Web 应用程序中不起作用
- node.js - 由于我的反应脚本中的问题,我在创建反应应用程序时出错
- azure-data-factory - 如何从 ADFv2 管道中获取管道运行 ID
- python - 在 python 上发送 SMS 时出现“botocore.exceptions.ParamValidationError:参数验证失败”错误
- input - 他们的任何替代品
- spring - Spring AMQP 恢复器不适用于 SimpleMessageListenerContainer