Python=を使用して、有向グラフで行われるプロセスをシミュレートしています。このプロセスのアニメーションを作成したいと思います。
私が遭遇した問題は、ほとんどのPythonグラフ視覚化ライブラリが有向エッジのペアを1つのエッジに結合することです。たとえば、 NetworkX は、2つのエッジのみを描画します。次のグラフを表示しますが、4つのエッジをそれぞれ個別に表示したいと思います。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.MultiDiGraph()
G.add_edges_from([
(1, 2),
(2, 3),
(3, 2),
(2, 1),
])
plt.figure(figsize=(8,8))
nx.draw(G)
このようなものを表示したいのですが、それぞれの平行なEdgeが別々に描かれています:
質問 RでのigraphのR相互エッジ は同じ問題を処理するようですが、R igraphライブラリでは、Python oneではなく)解決策があります。
既存のPythonグラフ視覚化ライブラリを使用してこのスタイルのプロットを作成する簡単な方法はありますか?マルチグラフをサポートできればおまけです。
外部プログラムを呼び出して画像を生成するソリューションを利用できます。一連のアニメーションフレーム全体を生成したいので、ソリューションを自動化する必要があります。
Graphviz ツールは、明確なエッジを表示するように見えます。
たとえば、これを与える:
digraph G {
A -> B;
A -> B;
A -> B;
B -> C;
B -> A;
C -> B;
}
to dot
は以下を生成します:
Graphvizの入力言語はかなり単純なので、自分で生成できますが、「python graphviz」を検索すると、 graphviz
module on PyPI を含むいくつかのライブラリが表示されます。
以下はpythonで、graphviz
モジュールを使用して上記のグラフを生成します:
from graphviz import Digraph
dot = Digraph()
dot.node('A', 'A')
dot.node('B', 'B')
dot.node('C', 'C')
dot.edges(['AB', 'AB', 'AB', 'BC', 'BA', 'CB'])
print(dot.source)
dot.render(file_name, view=True)
NetworkXを使用して、ファイルI/Oを回避し、レイアウトにpydotを介してドットを使用する可能な回避策は次のとおりです。
_import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from io import BytesIO
g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g) # d is a pydot graph object, dot options can be easily set
# attributes get converted from networkx,
# use set methods to control dot attributes after creation
png_str = d.create_png()
sio = BytesIO() # file-like string, appropriate for imread below
sio.write(png_str)
sio.seek(0)
img = mpimg.imread(sio)
imgplot = plt.imshow(img)
_
seek(0)
が必要な理由については、 Pythonで文字列から画像を作成する方法をご覧ください
IPython(qt)コンソール内の場合、上記はインラインで出力され、より直接的なアプローチは次のとおりです。
_import networkx as nx
from IPython.display import Image
g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g)
png_str = d.create_png()
Image(data=png_str)
_
少し遅れているかもしれませんが、問題の別の解決策を見つけたので、誰かが同じ問題を抱えている場合に役立つように投稿します。これはnx.drawに connectionstyle 引数を追加しています:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.MultiDiGraph()
G.add_edges_from([
(1, 2),
(2, 3),
(3, 2),
(2, 1),
])
plt.figure(figsize=(8,8))
nx.draw(G, connectionstyle='arc3, rad = 0.1',)
ここに結果が表示されます: