Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

PythonのGraphviz グラフレイアウトの変更

公開日 2024-10-27

この記事ではPythonのGraphvizでグラフのレイアウトを変更する方法を解説します。 レイアウトエンジンと、ノードの配置方向の変更について順に示します。

レイアウトエンジンの変更

Graphvizには複数のレイアウトエンジン(描画用プログラム)が実装されており、それを切り替えることでレイアウトを変更します。 レイアウトエンジンを変更する方法はいくつかありますが、ここでは2つ説明します。 1つはGraph(無向グラフ)やDigraph(有向グラフ)のengineオプションで指定する方法です。

from graphviz import Digraph

graph = Digraph(engine="neato")

graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node2", "node5")

graph
Loading...

もう1つはrender()メソッドのengineオプションで指定する方法です。

from IPython.display import Image

Image(graph.render(engine="dot", format="png"))
<IPython.core.display.Image object>

指定できるレイアウトエンジンは以下の通りです。

  • dot: 階層的なレイアウト(デフォルト)

  • neato: ばねモデル。ノード数が100程度以下の無効グラフ向け

  • fdp: ばねモデル。neatoより大規模な無向グラフ向け。サブグラフ向け

  • sfdp: fdpをより大規模な無向グラフに対応させたもの

  • circo: 円形レイアウト。ネットワーク構造などの描画向け

  • twopi: 放射状レイアウト

  • osage: 格子状レイアウト。クラスター構造の描画向け

  • patchwork: タイル状レイアウト

「ばねモデル」とは隣接するノード同士が適度に離れるモデルのことです。

なお、利用可能なレイアウトエンジンの一覧はgraphviz.ENGINESでも確認できます。

import graphviz

print(graphviz.ENGINES)
{'dot', 'neato', 'patchwork', 'circo', 'twopi', 'osage', 'sfdp', 'fdp'}

以下に各レイアウトエンジンのサンプルを示します。

dot

dotは階層構造に適したレイアウトエンジンです。

graph = Digraph(engine="dot")

graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node2", "node5")
graph.edge("node3", "node6")

graph
Loading...

neato

neatoはばねモデルを用いたレイアウトエンジンで、比較的小規模なグラフ(ノード数100程度以下)の無効グラフに適しています。

from graphviz import Graph

graph = Graph(engine="neato")

graph.edge("node1", "node2")
graph.edge("node2", "node3")
graph.edge("node3", "node4")
graph.edge("node4", "node5")
graph.edge("node5", "node2")

graph
Loading...

fdp

fdp (Force-Directed Placement) はばねモデルを用いたレイアウトエンジンで、neatoより大規模な無向グラフ向けです。また、サブグラフ(クラスター)を含む場合にも適しています。

graph = Graph(engine="fdp")

graph.edge("node1", "node2")
graph.edge("node2", "node3")
graph.edge("node3", "node4")
graph.edge("node4", "node5")
graph.edge("node5", "node2")

graph
Loading...

sfdp

sfdp (Scalable Force-Directed Placement) はfdpを大規模な無向グラフに対応させたレイアウトエンジンです。

graph = Graph(engine="sfdp")

graph.edge("node1", "node2")
graph.edge("node2", "node3")
graph.edge("node3", "node4")
graph.edge("node4", "node5")
graph.edge("node5", "node2")

graph
Loading...

circo

circoは円形の構造を描画するのに適したレイアウトエンジンです。ネットワーク構造などの描画に向いています。

graph = Graph(engine="circo")

graph.edge("node1", "node2")
graph.edge("node2", "node3")
graph.edge("node3", "node4")
graph.edge("node4", "node5")
graph.edge("node5", "node6")
graph.edge("node6", "node1")

graph.edge("node1", "node10")
graph.edge("node10", "node11")

graph.edge("node11", "node12")
graph.edge("node12", "node13")
graph.edge("node13", "node14")
graph.edge("node14", "node15")
graph.edge("node15", "node16")
graph.edge("node16", "node11")

graph
Loading...

twopi

twopiは放射状の構造を描画するのに適したレイアウトエンジンです。 中心ノード(以下ではnode0)から放射状にノードが配置されます。

graph = Graph(engine="twopi")

graph.edge("node0", "node1")
graph.edge("node0", "node2")
graph.edge("node0", "node3")
graph.edge("node0", "node4")
graph.edge("node0", "node5")
graph.edge("node0", "node6")

graph.edge("node1", "node11")
graph.edge("node2", "node12")
graph.edge("node3", "node13")
graph.edge("node4", "node14")
graph.edge("node5", "node15")

graph
Loading...

osage

osageは格子状の構造を描画するのに適したレイアウトエンジンです。

graph = Graph(engine="osage")

graph.edge("node1", "node2")
graph.edge("node2", "node3")
graph.edge("node3", "node4")
graph.edge("node4", "node5")
graph.edge("node5", "node6")
graph.edge("node6", "node7")
graph.edge("node7", "node8")
graph.edge("node8", "node9")

graph
Loading...

patchwork

patchworkはタイル状にノードを配置するレイアウトエンジンです。 ノード間の関係は図示されません。 各ノードのarea属性でノードの面積を指定します(デフォルト値は1)。

株式会社の時価総額の可視化などに用いられることがあります。 なお、タイルの色を変更する場合、ノードの属性をstyle="filled"として、fillcolorで色を指定します。

graph = Graph(engine="patchwork")

graph.attr("node", style="filled")

graph.node("A Airline", area="25", fillcolor="springgreen")
graph.node("B Bank", area="20", fillcolor="orangered")
graph.node("C Computer", area="15", fillcolor="orangered")
graph.node("D Development ", area="10")

graph
Loading...

ノード配置方向の変更

ノードを配置する方向を変更するには、グラフのrankdirパラメータを変更します。 rankdirには以下の4つを指定できます。

  • TB: 上から下 (top to bottom, デフォルト値)

  • BT: 下から上 (bottom to top)

  • LR: 左から右 (left to right)

  • RL: 右から左 (right to left)

Pythonのgraphvizの場合、グラフオブジェクトのattr属性でrankdirパラメータを指定します。 以下に例を示します。

graph = Digraph(engine="dot")

graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node2", "node5")
graph.edge("node3", "node6")

graph.attr(rankdir="TB")
graph
Loading...
graph.attr(rankdir="BT")
graph
Loading...
graph.attr(rankdir="LR")
graph
Loading...
graph.attr(rankdir="RL")
graph
Loading...