Matplotlib 和 Networkx - 绘制自循环节点
Matplotlib and Networkx - drawing a self loop node
我有这个功能,我想画一个自循环。我该怎么做?
边缘存在,但我认为这只是这个例子中的一个点是 (1,1),我无法添加节点的名称。
我的目标是从邻接矩阵画出一个图。有没有更好的方法来做到这一点?
import networkx as nx
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch, Circle
import numpy as np
def draw_network(G,pos,ax,sg=None):
for n in G:
c=Circle(pos[n],radius=0.05,alpha=0.7)
ax.add_patch(c)
G.node[n]['patch']=c
x,y=pos[n]
seen={}
for (u,v,d) in G.edges(data=True):
n1=G.node[u]['patch']
n2=G.node[v]['patch']
rad=0.1
if (u,v) in seen:
rad=seen.get((u,v))
rad=(rad+np.sign(rad)*0.1)*-1
alpha=0.5
color='k'
e = FancyArrowPatch(n1.center,n2.center,patchA=n1,patchB=n2,
arrowstyle='-|>',
connectionstyle='arc3,rad=%s'%rad,
mutation_scale=10.0,
lw=2,
alpha=alpha,
color=color)
seen[(u,v)]=rad
ax.add_patch(e)
return e
G=nx.MultiDiGraph([(1,2),(1,1),(1,2),(2,3),(3,4),(2,4),
(1,2),(1,2),(1,2),(2,3),(3,4),(2,4)]
)
pos=nx.spring_layout(G)
ax=plt.gca()
draw_network(G,pos,ax)
ax.autoscale()
plt.axis('equal')
plt.axis('off')
plt.show()
看来您的方法是使用 matplotlib 的高级方法,但我仍然建议使用专门的绘图库 (as does the networkx documentation)。随着图表变大,出现了更多问题——但这些库中已经解决的问题。
“go-to”选项是 graphviz,它可以很好地处理绘图 multi-graphs。您可以从 networkx 图形写入点文件,然后使用图形绘制工具之一(例如 dot、neato 等)。
这是一个例子,建立在 and multigraph edge attributes:
import networkx as nx
from networkx.drawing.nx_agraph import to_agraph
# define the graph as per your question
G=nx.MultiDiGraph([(1,2),(1,1),(1,2),(2,3),(3,4),(2,4),
(1,2),(1,2),(1,2),(2,3),(3,4),(2,4)])
# add graphviz layout options (see
G.graph['edge'] = {'arrowsize': '0.6', 'splines': 'curved'}
G.graph['graph'] = {'scale': '3'}
# adding attributes to edges in multigraphs is more complicated but see
#
G[1][1][0]['color']='red'
A = to_agraph(G)
A.layout('dot')
A.draw('multi.png')
请注意,您还可以从 ipython shell 中轻松调用绘图:
我有这个功能,我想画一个自循环。我该怎么做?
边缘存在,但我认为这只是这个例子中的一个点是 (1,1),我无法添加节点的名称。
我的目标是从邻接矩阵画出一个图。有没有更好的方法来做到这一点?
import networkx as nx
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch, Circle
import numpy as np
def draw_network(G,pos,ax,sg=None):
for n in G:
c=Circle(pos[n],radius=0.05,alpha=0.7)
ax.add_patch(c)
G.node[n]['patch']=c
x,y=pos[n]
seen={}
for (u,v,d) in G.edges(data=True):
n1=G.node[u]['patch']
n2=G.node[v]['patch']
rad=0.1
if (u,v) in seen:
rad=seen.get((u,v))
rad=(rad+np.sign(rad)*0.1)*-1
alpha=0.5
color='k'
e = FancyArrowPatch(n1.center,n2.center,patchA=n1,patchB=n2,
arrowstyle='-|>',
connectionstyle='arc3,rad=%s'%rad,
mutation_scale=10.0,
lw=2,
alpha=alpha,
color=color)
seen[(u,v)]=rad
ax.add_patch(e)
return e
G=nx.MultiDiGraph([(1,2),(1,1),(1,2),(2,3),(3,4),(2,4),
(1,2),(1,2),(1,2),(2,3),(3,4),(2,4)]
)
pos=nx.spring_layout(G)
ax=plt.gca()
draw_network(G,pos,ax)
ax.autoscale()
plt.axis('equal')
plt.axis('off')
plt.show()
看来您的方法是使用 matplotlib 的高级方法,但我仍然建议使用专门的绘图库 (as does the networkx documentation)。随着图表变大,出现了更多问题——但这些库中已经解决的问题。
“go-to”选项是 graphviz,它可以很好地处理绘图 multi-graphs。您可以从 networkx 图形写入点文件,然后使用图形绘制工具之一(例如 dot、neato 等)。
这是一个例子,建立在
import networkx as nx
from networkx.drawing.nx_agraph import to_agraph
# define the graph as per your question
G=nx.MultiDiGraph([(1,2),(1,1),(1,2),(2,3),(3,4),(2,4),
(1,2),(1,2),(1,2),(2,3),(3,4),(2,4)])
# add graphviz layout options (see
G.graph['edge'] = {'arrowsize': '0.6', 'splines': 'curved'}
G.graph['graph'] = {'scale': '3'}
# adding attributes to edges in multigraphs is more complicated but see
#
G[1][1][0]['color']='red'
A = to_agraph(G)
A.layout('dot')
A.draw('multi.png')
请注意,您还可以从 ipython shell 中轻松调用绘图: