从 grid_2d_graph 一致删除节点
Consistent removal of nodes from grid_2d_graph
假设我有一个由 NxN=100x100
个节点组成的常规二维网格图 G
。我通过调用创建这样的网络:
N=100
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() ) #Dictionary of all positions
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
我得到的结果类似于这张图片左侧显示的结果:
现在,假设我的网络经历了一个破坏性事件,导致许多节点发生故障(图片右侧)。我的图 G
不再由相同数量的节点组成:图 G2
现在拥有 K<NxN
个节点。鉴于这种情况,我希望能够通过调用来绘制 G2
:
G2=G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
nx.draw_networkx(G2, pos=pos, labels=labels,with_labels=False, node_size=10)
我的问题。 我该怎么做才能确保位置字典 pos
不被更改? 这意味着:如果节点0
在(0,0)
位置(左上角)在1)的情况下它不失败,则它必须出现在情况 2) 中的相同位置。这样,两个网络就可以比较了,因为第二个网络只是第一个网络的 "transformation"。 谢谢!
您可以通过将 (i,j) 中的节点重新标记为您在标签字典中的数字上看到的数字来实现。然后删除失败的节点。最后,通过简单地反转 labels 字典,调整 pos 字典以将位置映射到节点的新标签。这是我在您的代码后添加的内容:
nx.relabel_nodes(G,labels,False)
G.remove_nodes_from([0,4,12,18])
pos = {y:x for x,y in labels.iteritems()}
nx.draw_networkx(G, pos=pos, with_labels=True, node_size = 300)
对于 N = 5 和故障节点 [0,4,12,18],这是我在删除故障节点之前(左)和之后(右)得到的结果。
我很难理解您问这个问题的原因 - 代码基本上应该完全按照您的要求工作。但是,您有一个错误,这可能是导致您提出这个问题的原因。
G2= G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
这将使 G2
变为 None
。 G.remove_nodes_from(L)
从 G
中删除 L
中的节点。它不会创建看起来像 G
但没有这些节点的新图。所以它没有 return 任何东西。因此 G2
没有被赋予任何价值。图 G
已删除这些节点。
所以以下应该有效:
N=100
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() ) #Dictionary of all positions
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
#find failed nodes here
G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
pos
在此代码中从未更改。
我想扩展一下@AbdallahSobehy 的回答。但是,为了更普遍地重用 networkx
图,我建议将位置和标签信息存储在图结构中,而不是在单独的容器中。
从图表的简化版本开始(N = 5
):
N = 5
G = nx.grid_2d_graph(N,N)
pos = dict((n, n) for n in G.nodes())
labels = dict(((i, j), i + (N-1-j) * N) for i, j in G.nodes())
可以将 pos
和 label
字典存储为图形属性:
nx.set_node_attributes(G, 'pos', pos)
nx.set_node_attributes(G, 'labels', labels)
并将它们用于绘图:
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),
labels=nx.get_node_attributes(G, 'labels'),
with_labels=True, node_size=500)
您稍后可以在图中执行任何操作,例如删除一些节点:
G.remove_nodes_from([(0,0),(0,2),(2,2),(2,1)])
并重新绘制图形,实际上不需要重新计算 pos
或 label
字典,因为条目会随着图形操作自动更新。下一行与上面的绘图调用完全相同:
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),
labels=nx.get_node_attributes(G, 'labels'),
with_labels=True, node_size=500)
但这一次,产生了不同的图像:
简而言之:将所有内容存储在 node/edge 属性中,因为它们会随着图表的变化而自动更新。
假设我有一个由 NxN=100x100
个节点组成的常规二维网格图 G
。我通过调用创建这样的网络:
N=100
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() ) #Dictionary of all positions
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
我得到的结果类似于这张图片左侧显示的结果:
现在,假设我的网络经历了一个破坏性事件,导致许多节点发生故障(图片右侧)。我的图 G
不再由相同数量的节点组成:图 G2
现在拥有 K<NxN
个节点。鉴于这种情况,我希望能够通过调用来绘制 G2
:
G2=G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
nx.draw_networkx(G2, pos=pos, labels=labels,with_labels=False, node_size=10)
我的问题。 我该怎么做才能确保位置字典 pos
不被更改? 这意味着:如果节点0
在(0,0)
位置(左上角)在1)的情况下它不失败,则它必须出现在情况 2) 中的相同位置。这样,两个网络就可以比较了,因为第二个网络只是第一个网络的 "transformation"。 谢谢!
您可以通过将 (i,j) 中的节点重新标记为您在标签字典中的数字上看到的数字来实现。然后删除失败的节点。最后,通过简单地反转 labels 字典,调整 pos 字典以将位置映射到节点的新标签。这是我在您的代码后添加的内容:
nx.relabel_nodes(G,labels,False)
G.remove_nodes_from([0,4,12,18])
pos = {y:x for x,y in labels.iteritems()}
nx.draw_networkx(G, pos=pos, with_labels=True, node_size = 300)
对于 N = 5 和故障节点 [0,4,12,18],这是我在删除故障节点之前(左)和之后(右)得到的结果。
我很难理解您问这个问题的原因 - 代码基本上应该完全按照您的要求工作。但是,您有一个错误,这可能是导致您提出这个问题的原因。
G2= G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
这将使 G2
变为 None
。 G.remove_nodes_from(L)
从 G
中删除 L
中的节点。它不会创建看起来像 G
但没有这些节点的新图。所以它没有 return 任何东西。因此 G2
没有被赋予任何价值。图 G
已删除这些节点。
所以以下应该有效:
N=100
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() ) #Dictionary of all positions
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
#find failed nodes here
G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
pos
在此代码中从未更改。
我想扩展一下@AbdallahSobehy 的回答。但是,为了更普遍地重用 networkx
图,我建议将位置和标签信息存储在图结构中,而不是在单独的容器中。
从图表的简化版本开始(N = 5
):
N = 5
G = nx.grid_2d_graph(N,N)
pos = dict((n, n) for n in G.nodes())
labels = dict(((i, j), i + (N-1-j) * N) for i, j in G.nodes())
可以将 pos
和 label
字典存储为图形属性:
nx.set_node_attributes(G, 'pos', pos)
nx.set_node_attributes(G, 'labels', labels)
并将它们用于绘图:
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),
labels=nx.get_node_attributes(G, 'labels'),
with_labels=True, node_size=500)
您稍后可以在图中执行任何操作,例如删除一些节点:
G.remove_nodes_from([(0,0),(0,2),(2,2),(2,1)])
并重新绘制图形,实际上不需要重新计算 pos
或 label
字典,因为条目会随着图形操作自动更新。下一行与上面的绘图调用完全相同:
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),
labels=nx.get_node_attributes(G, 'labels'),
with_labels=True, node_size=500)
但这一次,产生了不同的图像:
简而言之:将所有内容存储在 node/edge 属性中,因为它们会随着图表的变化而自动更新。