⬜
NetworkXを使ってみる(描画編)(Python)
こんにちは、沙代です。
秋っぽい日も増えて参りましたね。
グラフを画像化するのをあまりやったことがなかったので、まとめてみようと思いました。
MacOS Montery 12.6.2 (M1 Pro)
Python 3.10.0
matplotlib 3.9.2
networkx 3.3
環境構築してみる
分離して、使い捨てする場合、仮想環境を構築します。
mkdir tmp && cd tmp
pyenv local 3.10.0
python -m venv venv
. venv/bin/activate
pip install --upgrade pip
pip install matplotlib "networkx[default]" japanize-matplotlib jupyterlab
(jupyterlabは、人によってはいらないかもしれません)
動かしてみる
import networkx as nx
import matplotlib.pyplot as plt
# 無向グラフの作成
G = nx.Graph()
# ノードの追加
G.add_node(1)
G.add_node(2)
G.add_node(3)
# エッジの追加
G.add_edge(1, 2)
G.add_edge(2, 3)
# グラフの描画
nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_color='black')
# グラフの表示
plt.show()
ちゃんと、「1」「2」「3」のノードが追加されていて、1-2, 2-3で結ばれていますね。
有効グラフにしてみる
import networkx as nx
import matplotlib.pyplot as plt
# 有向グラフの作成
G = nx.DiGraph()
# ノードの追加
G.add_node(1)
G.add_node(2)
G.add_node(3)
# エッジの追加
G.add_edge(1, 2)
G.add_edge(2, 3)
# グラフの描画
nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_color='black')
# グラフの表示
plt.show()
G = nx.Graph()
の代わりにG = nx.DiGraph()
を使ってみます。
日本語ラベルを使ってみる
もし単純に日本語をラベルに使用しようとすると、上手に表示されません。
import networkx as nx
import matplotlib.pyplot as plt
# 有向グラフの作成
G = nx.DiGraph()
# ノードの追加
G.add_node("ぐり")
G.add_node("と")
G.add_node("ぐら")
# エッジの追加
G.add_edge("ぐり", "と")
G.add_edge("と", "ぐら")
# グラフの描画
nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_color='black')
# グラフの表示
plt.show()
解決していきます。
私の手元では、"IPAexGothic"のフォントがありました。
import matplotlib
for f in matplotlib.font_manager.fontManager.ttflist:
if "IPAexGothic" in f.name:
print(f.name)
# Output: IPAexGothic
japanize-matplotlibと併せて、font_familyを指定して日本語化していきます。
import networkx as nx
import matplotlib.pyplot as plt
import japanize_matplotlib
# 有向グラフの作成
G = nx.DiGraph()
# ノードの追加
G.add_node("ぐり")
G.add_node("と")
G.add_node("ぐら")
# エッジの追加
G.add_edge("ぐり", "と")
G.add_edge("と", "ぐら")
# グラフの描画
nx.draw(G, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_color='black', font_family='IPAexGothic')
# グラフの表示
plt.show()
出来ました!
出力に再現性を持たせる
実は、毎回出力が異なってしまいます。
これは、spring_layout
という関数でseed
値を指定した上でpositionを決定し、
それをnx.draw
に渡すことで回避できます。
import networkx as nx
import matplotlib.pyplot as plt
import japanize_matplotlib
# 有向グラフの作成
G = nx.DiGraph()
# ノードの追加
G.add_node("ぐり")
G.add_node("と")
G.add_node("ぐら")
# エッジの追加
G.add_edge("ぐり", "と")
G.add_edge("と", "ぐら")
# spring_layout でノードの位置を決定
pos = nx.spring_layout(G, seed=42)
# グラフの描画
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_color='black', font_family='IPAexGothic')
# グラフの表示
plt.show()
エッジに重みを持たせる
エッジに重み(weight)を持たせることで、重みが大きいエッジはより短くなり、重みが小さいエッジはより長く配置されます。
(差のあるところだけ再表示)
# エッジの追加と重みの設定
G.add_edge("ぐり", "と", weight=100)
G.add_edge("と", "ぐら", weight=0.5)
片付け
今回、仮想環境に(を)作成したので、以下のようにしてお片づけしました。
deactivate
cd .. && rm -rf tmp
参考にさせていただいたページ
Discussion