networkxで有向グラフを図示する際に曲線を描きたい場合があるが、そのためのオプションが極めて見つけづらいものだったのでメモ。
直線で描いた場合の例
以下のような隣接行列を考える。これは3×3の完全グラフとなる。
\begin{pmatrix}
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\end{pmatrix}
networkxを利用して通常の描画を行う。
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
W = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
G = nx.from_numpy_array(W, create_using=nx.DiGraph) # 有向グラフにする際のオプション
nx.draw_networkx(G, arrows=True)
plt.show()
plt.close()
これでも表示そのものはできているが、表示に接続強度等の情報を持たせたいときに双方の線が重なると見づらくなってしまう。
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
W = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
G = nx.from_numpy_array(W, create_using=nx.DiGraph)
nx.set_edge_attributes(G, name='weight', values=1)
# 接続に重みの情報を乗せる、一方向だけ強くする
G.edges[1, 0]['weight'] = 3
G.edges[2, 1]['weight'] = 3
G.edges[0, 2]['weight'] = 3
nx.draw_networkx(G, arrows=True, width=[v['weight'] for v in G.edges.values()])
plt.show()
plt.close()
↑線の片方だけが太い=強いが、線の区別がつかない
解決
ここで公式ドキュメント内に、draw_networkx()の引数として設定するオプションのキーワードは(networkx.draw_networkx_nodes(), networkx.draw_networkx_edges(), and networkx.draw_networkx_labels())の項を参照とあるので、draw_networkx_edges()の項目を見るとconnectionstyle
というオプションがある。
これを使ってみる。
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
W = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
G = nx.from_numpy_array(W, create_using=nx.DiGraph)
nx.set_edge_attributes(G, name='weight', values=1)
G.edges[1, 0]['weight'] = 3
G.edges[2, 1]['weight'] = 3
G.edges[0, 2]['weight'] = 3
nx.draw_networkx(G, arrows=True, width=[v['weight'] for v in G.edges.values()], connectionstyle="arc3, rad=0.2")
plt.show()
plt.close()
ここでconnectionstyle
の詳細についてはmatplotlibのドキュメントを参照する。
これで線の双方を区別した形で図示を行うことができた。