使用pydot与networkx

huangapple go评论69阅读模式
英文:

Using pydot with networkx

问题

我试图绘制以下列表,使边的粗细与权重成比例:

g_list = [('Alpha', 'Alpha', 7.06), ('Alpha', 'Bravo', 0.98), ('Alpha', 'Charlie', 0.0), ('Alpha', 'Delta', 0.0), ('Alpha', 'Echo', 1.57), ('Alpha', 'Foxtrot', 2.16), ('Alpha', 'Golf', 1.57), ('Alpha', 'Hotel', 0.39), ('Alpha', 'India', 0.0), ('Alpha', 'Juliet', 0.2), ('Alpha', 'Kilo', 0.59), ('Bravo', 'Alpha', 1.66), ('Bravo', 'Bravo', 8.54), ('Bravo', 'Charlie', 1.21), ('Bravo', 'Delta', 1.78), ('Bravo', 'Echo', 0.25), ('Bravo', 'Foxtrot', 0.76), ('Bravo', 'Golf', 1.66), ('Bravo', 'Hotel', 1.59), ('Bravo', 'India', 2.87), ('Bravo', 'Juliet', 1.72), ('Bravo', 'Kilo', 1.27), ('Charlie', 'Alpha', 1.0), ('Charlie', 'Bravo', 2.5), ('Charlie', 'Charlie', 7.0), ('Charlie', 'Delta', 5.0), ('Charlie', 'Echo', 0.0), ('Charlie', 'Foxtrot', 0.5), ('Charlie', 'Golf', 3.0), ('Charlie', 'Hotel', 0.0), ('Charlie', 'India', 0.5), ('Charlie', 'Juliet', 2.5), ('Charlie', 'Kilo', 1.5)]

以下代码有效,但不够美观:

import networkx as nx

G = nx.Graph()
for i in range(len(g_list)):
    if ((g_list[i][0] != g_list[i][1]) and (g_list[i][2] != 0.0)):
        G.add_edge(g_list[i][0], g_list[i][1], weight=g_list[i][2])
pos = nx.spring_layout(G)
for edge in G.edges(data='weight'):
    nx.draw_networkx_edges(G, pos, edgelist=[edge], width=edge[2])
nx.draw_networkx(G, pos, with_labels=True, arrows=True, arrowstyle='<-', alpha=1, node_color='#ffffff')
plt.axis('off')
plt.savefig('graph.jpg')

所述的演示可以通过使用 pydot 来实现:

G = nx.DiGraph()
for i in range(len(g_list)):
    if ((g_list[i][0] != g_list[i][1]) and (g_list[i][2] != 0.0)):
        G.add_edge(g_list[i][1], g_list[i][0], weight=g_list[i][2])
p = nx.drawing.nx_pydot.to_pydot(G)
p.write_png('graph.png')

这是一个更美观的图形,但当我尝试添加可变粗细的边缘时,会回到第一个图形。有没有办法将这两种方法结合起来,以获得 pydot 的布局和对网络边缘的绘制控制?我尝试了以下方法,但仍然没有第二幅图中清晰的布局:

pos = nx.nx_pydot.pydot_layout(G, prog='dot')
nx.draw_networkx(G, pos, with_labels=True, arrows=True, arrowstyle='<-', alpha=1, node_color='#ffffff')
for edge in G.edges(data='weight'):
    nx.draw_networkx_edges(G, pos, edgelist=[edge], width=edge[2])

结果如下图,但仍然没有第二幅图中的清晰布局:

使用pydot与networkx

英文:

I am trying to plot the following list as a graph with edge thickness proportional to the weights.

g_list=[(&#39;Alpha&#39;, &#39;Alpha&#39;, 7.06), (&#39;Alpha&#39;, &#39;Bravo&#39;, 0.98), (&#39;Alpha&#39;, &#39;Charlie&#39;, 0.0), (&#39;Alpha&#39;, &#39;Delta&#39;, 0.0), (&#39;Alpha&#39;, &#39;Echo&#39;, 1.57), (&#39;Alpha&#39;, &#39;Foxtrot&#39;, 2.16), (&#39;Alpha&#39;, &#39;Golf&#39;, 1.57), (&#39;Alpha&#39;, &#39;Hotel&#39;, 0.39), (&#39;Alpha&#39;, &#39;India&#39;, 0.0), (&#39;Alpha&#39;, &#39;Juliet&#39;, 0.2), (&#39;Alpha&#39;, &#39;Kilo&#39;, 0.59), (&#39;Bravo&#39;, &#39;Alpha&#39;, 1.66), (&#39;Bravo&#39;, &#39;Bravo&#39;, 8.54), (&#39;Bravo&#39;, &#39;Charlie&#39;, 1.21), (&#39;Bravo&#39;, &#39;Delta&#39;, 1.78), (&#39;Bravo&#39;, &#39;Echo&#39;, 0.25), (&#39;Bravo&#39;, &#39;Foxtrot&#39;, 0.76), (&#39;Bravo&#39;, &#39;Golf&#39;, 1.66), (&#39;Bravo&#39;, &#39;Hotel&#39;, 1.59), (&#39;Bravo&#39;, &#39;India&#39;, 2.87), (&#39;Bravo&#39;, &#39;Juliet&#39;, 1.72), (&#39;Bravo&#39;, &#39;Kilo&#39;, 1.27), (&#39;Charlie&#39;, &#39;Alpha&#39;, 1.0), (&#39;Charlie&#39;, &#39;Bravo&#39;, 2.5), (&#39;Charlie&#39;, &#39;Charlie&#39;, 7.0), (&#39;Charlie&#39;, &#39;Delta&#39;, 5.0), (&#39;Charlie&#39;, &#39;Echo&#39;, 0.0), (&#39;Charlie&#39;, &#39;Foxtrot&#39;, 0.5), (&#39;Charlie&#39;, &#39;Golf&#39;, 3.0), (&#39;Charlie&#39;, &#39;Hotel&#39;, 0.0), (&#39;Charlie&#39;, &#39;India&#39;, 0.5), (&#39;Charlie&#39;, &#39;Juliet&#39;, 2.5), (&#39;Charlie&#39;, &#39;Kilo&#39;, 1.5)]

The following code works but is not pretty

import networkx as nx

G=nx.Graph()
for i in range(len(g_list)):
    if((g_list[i][0] != g_list[i][1]) and (g_list[i][2] != 0.0)):
        G.add_edge(g_list[i][0],g_list[i][1],weight=g_list[i][2])
pos = nx.spring_layout(G)
for edge in G.edges(data=&#39;weight&#39;):
    nx.draw_networkx_edges(G, pos, edgelist=[edge], width=edge[2])
nx.draw_networkx(G, pos, with_labels=True, arrows=True, arrowstyle=&#39;&lt;-&#39;, alpha=1, node_color=&#39;#ffffff&#39;)
plt.axis(&#39;off&#39;)
plt.savefig(&#39;graph.jpg&#39;)

使用pydot与networkx

The sort of presentation I'm looking for can be obtained using pydot as folllows

G=nx.DiGraph()
for i in range(len(g_list)):
    if((g_list[i][0] != g_list[i][1]) and (g_list[i][2] != 0.0)):
        G.add_edge(g_list[i][1],g_list[i][0],weight=g_list[i][2])
p=nx.drawing.nx_pydot.to_pydot(G)
p.write_png(&#39;graph.png&#39;)

使用pydot与networkx

This is a better looking graph but when I try to add the variable thickness edges back using

pos = nx.spring_layout(G)
for edge in G.edges(data=&#39;weight&#39;):
    nx.draw_networkx_edges(G, pos, edgelist=[edge], width=edge[2])
p=nx.drawing.nx_pydot.to_pydot(G)

I end up with the first graph again. Is there any way of combining the two approaches so that I get the layout of pydot and control over the drawing of the network edges? I have tried the following

pos=nx.nx_pydot.pydot_layout(G, prog=&#39;dot&#39;)
nx.draw_networkx(G, pos, with_labels=True, arrows=True, arrowstyle=&#39;&lt;-&#39;, alpha=1, node_color=&#39;#ffffff&#39;)
for edge in G.edges(data=&#39;weight&#39;):
    nx.draw_networkx_edges(G, pos, edgelist=[edge], width=edge[2])

with the following result, but still not the clear layout I get in the second graph.

使用pydot与networkx

答案1

得分: 1

如果你想要使用GraphViz的dot来呈现具有不同边线宽度的图形,你需要将weight转换为GraphViz可以理解的penwidth属性。

我发现使用实际的权重会使事情变得太厚重,所以下面是一种将权重的平方根作为penwidth的方法。

请注意,你也可以使用add_weighted_edges_from来一次性转换你的数据。

import math
import networkx as nx
from networkx.drawing.nx_pydot import to_pydot

g_list = [
    ("Alpha", "Alpha", 7.06),
    ("Alpha", "Bravo", 0.98),
    ("Alpha", "Charlie", 0.0),
    ("Alpha", "Delta", 0.0),
    ("Alpha", "Echo", 1.57),
    ("Alpha", "Foxtrot", 2.16),
    ("Alpha", "Golf", 1.57),
    ("Alpha", "Hotel", 0.39),
    ("Alpha", "India", 0.0),
    ("Alpha", "Juliet", 0.2),
    ("Alpha", "Kilo", 0.59),
    ("Bravo", "Alpha", 1.66),
    ("Bravo", "Bravo", 8.54),
    ("Bravo", "Charlie", 1.21),
    ("Bravo", "Delta", 1.78),
    ("Bravo", "Echo", 0.25),
    ("Bravo", "Foxtrot", 0.76),
    ("Bravo", "Golf", 1.66),
    ("Bravo", "Hotel", 1.59),
    ("Bravo", "India", 2.87),
    ("Bravo", "Juliet", 1.72),
    ("Bravo", "Kilo", 1.27),
    ("Charlie", "Alpha", 1.0),
    ("Charlie", "Bravo", 2.5),
    ("Charlie", "Charlie", 7.0),
    ("Charlie", "Delta", 5.0),
    ("Charlie", "Echo", 0.0),
    ("Charlie", "Foxtrot", 0.5),
    ("Charlie", "Golf", 3.0),
    ("Charlie", "Hotel", 0.0),
    ("Charlie", "India", 0.5),
    ("Charlie", "Juliet", 2.5),
    ("Charlie", "Kilo", 1.5),
]

graph = nx.DiGraph()
# 添加边,但反转方向,删除自环边和权重为零的边
graph.add_weighted_edges_from([(b, a, w) for (a, b, w) in g_list if w > 0 and a != b])

for edge in graph.edges().values():
    edge["penwidth"] = round(1 + math.sqrt(edge["weight"]), 2)

p = to_pydot(graph)
p.write_png("graph.png")

输出结果如下:

使用pydot与networkx

英文:

If you want to use GraphViz's dot to render your graph with varying edge line width, you'll need to convert the weight to a penwidth attribute that GraphViz understands.

I found using the actual weight made things way too thick, so here's something that takes the square root of the weight.

Note you can use add_weighted_edges_from to convert your data in one fell swoop, too.

import math
import networkx as nx
from networkx.drawing.nx_pydot import to_pydot
g_list = [
(&quot;Alpha&quot;, &quot;Alpha&quot;, 7.06),
(&quot;Alpha&quot;, &quot;Bravo&quot;, 0.98),
(&quot;Alpha&quot;, &quot;Charlie&quot;, 0.0),
(&quot;Alpha&quot;, &quot;Delta&quot;, 0.0),
(&quot;Alpha&quot;, &quot;Echo&quot;, 1.57),
(&quot;Alpha&quot;, &quot;Foxtrot&quot;, 2.16),
(&quot;Alpha&quot;, &quot;Golf&quot;, 1.57),
(&quot;Alpha&quot;, &quot;Hotel&quot;, 0.39),
(&quot;Alpha&quot;, &quot;India&quot;, 0.0),
(&quot;Alpha&quot;, &quot;Juliet&quot;, 0.2),
(&quot;Alpha&quot;, &quot;Kilo&quot;, 0.59),
(&quot;Bravo&quot;, &quot;Alpha&quot;, 1.66),
(&quot;Bravo&quot;, &quot;Bravo&quot;, 8.54),
(&quot;Bravo&quot;, &quot;Charlie&quot;, 1.21),
(&quot;Bravo&quot;, &quot;Delta&quot;, 1.78),
(&quot;Bravo&quot;, &quot;Echo&quot;, 0.25),
(&quot;Bravo&quot;, &quot;Foxtrot&quot;, 0.76),
(&quot;Bravo&quot;, &quot;Golf&quot;, 1.66),
(&quot;Bravo&quot;, &quot;Hotel&quot;, 1.59),
(&quot;Bravo&quot;, &quot;India&quot;, 2.87),
(&quot;Bravo&quot;, &quot;Juliet&quot;, 1.72),
(&quot;Bravo&quot;, &quot;Kilo&quot;, 1.27),
(&quot;Charlie&quot;, &quot;Alpha&quot;, 1.0),
(&quot;Charlie&quot;, &quot;Bravo&quot;, 2.5),
(&quot;Charlie&quot;, &quot;Charlie&quot;, 7.0),
(&quot;Charlie&quot;, &quot;Delta&quot;, 5.0),
(&quot;Charlie&quot;, &quot;Echo&quot;, 0.0),
(&quot;Charlie&quot;, &quot;Foxtrot&quot;, 0.5),
(&quot;Charlie&quot;, &quot;Golf&quot;, 3.0),
(&quot;Charlie&quot;, &quot;Hotel&quot;, 0.0),
(&quot;Charlie&quot;, &quot;India&quot;, 0.5),
(&quot;Charlie&quot;, &quot;Juliet&quot;, 2.5),
(&quot;Charlie&quot;, &quot;Kilo&quot;, 1.5),
]
graph = nx.DiGraph()
# Add edges, but reverse direction, remove self-loops, and remove zero-weight edges
graph.add_weighted_edges_from([(b, a, w) for (a, b, w) in g_list if w &gt; 0 and a != b])
for edge in graph.edges().values():
edge[&quot;penwidth&quot;] = round(1 + math.sqrt(edge[&quot;weight&quot;]), 2)
p = to_pydot(graph)
p.write_png(&quot;graph.png&quot;)

The output is
使用pydot与networkx

huangapple
  • 本文由 发表于 2023年2月14日 19:40:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75447305.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定