
フローチャートや簡易的な関係図などをWordやPowerPointで作成すると、矢印の長さや枠のサイズを調整するのが意外と面倒だと感じることがあります。Python + Graphvizを使うと、手作業のミスを減らし一貫性のあるグラフを生成できることや、データを変更すればグラフを即座に更新できるなどの利点があります。また、Pythonの条件文と組み合わせることにより、条件に応じてグラフを変更するなども可能になります。この記事では、Graphvizを使ってグラフを自動生成する方法を紹介します。
目次
- Graphviz本体のインストール
- Graphvizライブラリのインストール
- 基本的な使い方
- 日本語フォントの使用
- ノード作成の主なオプション
- エッジ作成の主なオプション
- レイアウトの変更
- まとめ
- 参考情報
Graphviz本体のインストール
Graphvizはノード(点)とエッジ(線)で構成されるグラフ構造を、自動的にレイアウトして描画するオープンソースのグラフ描画ツールです。フローチャートや組織図、ネットワーク図、系統樹など、さまざまな種類のグラフを描画できます。GraphizはDOT言語と呼ばれるシンプルなテキストベースの記述言語を使用し、描画したグラフはPNGやJPEG、SVG、PDFなど様々な画像形式で出力できます。
Graphviz本体は以下のサイトからインストールできます。
https://graphviz.gitlab.io/download/
Windowsの場合は、32bit版と64bit版がありますので、使用しているOSのビット数のEXE Installerファイルを選択してダウンロードします。
インストーラを実行した後は、説明にそって「次へ」ボタンを順に押すとインストールできますが、その途中でPythonからGraphvizを実行できるようにPATHの設定を行います。
下の画面が表示されたときに「Add Graphviz to the system Path ...」のいずれかを選択するとPATHが設定されます。「... for all users」は全ユーザーに対して、「... for current user」は現在のユーザーに対してPATHを追加します。
GraphvizをインストールしたフォルダにあるbinフォルダにPATHを通す必要があります。デフォルトではC:\Program Files\Graphviz\binになります。
LinuxやMacの場合には、パッケージ管理ソフトによりgraphvizをインストールします。
(https://graphviz.gitlab.io/download/を参考)
例えば、Ubuntuの場合は、
sudo apt install graphviz
となります。
Graphvizライブラリのインストール
PythonでGraphvizを使用するために、Graphvizライブラリをインストールします。
pip install graphviz
Graphvizライブラリを使用するためには、先ほどインストールしたGraphviz本体がインストールされており、そこにPATHを通している必要があります。
基本的な使い方
GraphvizライブラリのAPIを使用する
Graphvizライブラリを使用する場合の基本的な構造はとてもシンプルです。
まず有向グラフ(graphviz.Digraph
) か 無向グラフ(graphviz.Graph
) を選択し、必要に応じて出力形式を指定します。
次に、ノードを定義(dot.node
)して、ノードとノードをエッジで接続(dot.edge
)します。
そして、最後にグラフをファイル出力(dot.render
)または画面に表示(dot.view
)するという流れになります。
import graphviz
# グラフの種類を有向グラフ、出力形式をpngに設定
dot = graphviz.Digraph(format='png')
# グラフの種類を無向グラフ、出力形式をpngに設定
#dot = graphviz.Graph(format='png')
# ノードの追加
dot.node('A1', 'Kin Arthur')
dot.node('A2', 'Sir Bedevere the Wise')
dot.node('A3', 'Sir Lancelot the Brave')
# エッジの追加
dot.edges([('A1','A2'), ('A1','A3')])
dot.edge('A2', 'A3', constraint='false')
# 画像を出力
dot.render()
# グラフを表示
# dot.view()
実行すると、次の画像が得られます。
サンプルプログラムの各行について説明します。まず最初に、graphvizライブラリをインポートする必要があります。これにより、ライブラリが提供する様々な関数を使用することができます。
import graphviz
次に、作成するグラフの種類を指定します。
グラフには有向グラフと無向グラフがあります。有向グラフはノードとノードをつなぐエッジに向き(つまり矢印)があるグラフのことです。一方で、無向グラフはエッジに向き(つまり矢印)がないグラフのことです。以下の部分でどちらを使用するかを選択します。
# グラフの種類を有向グラフ、出力形式をpngに設定
dot = graphviz.Digraph(format='png')
# グラフの種類を無向グラフ、出力形式をpngに設定
dot = graphviz.Graph(format='png')
このサンプルプログラムでは、Digraph
を使用しているため、有向グラフが作成されます。無向グラフを使用したい場合はDigraph
の代わりにGraph
を使います。出力形式にはpng
ファイルを選択していますが、JPEG、PDF、SVGなど様々な出力形式に対応しています。
次に、ノードを定義します。ノードは上の図で〇でかかれたもののことで、グラフの頂点を意味します。
# ノードの追加
dot.node('A1', 'Kin Arthur')
dot.node('A2', 'Sir Bedevere the Wise')
dot.node('A3', 'Sir Lancelot the Brave')
ここで、dot.node(識別子, ラベル)
という形でノード(頂点)を追加しています。'A1'
などは ノードの識別子(内部ID)でノード間をエッジで接続するときに使い、グラフには表示されません。また、'Kin Arthur'
などはラベル(表示名)で、グラフのノードに実際に表示される文字になります。
ノードを定義した後は、ノード間をエッジで接続します。ここでは、エッジを接続する方法としてedges
を使用する方法とedge
を使用する方法を記載しています。edges
はリストを使用して複数のエッジを一括追加できます。エッジを接続するときは、接続するノードの識別子を指定します。
# エッジの追加
dot.edges([('A1','A2'), ('A1','A3')])
dot.edge('A2', 'A3', constraint='false')
最初の文はA1→A2とA1→A3のエッジを追加しています。2つ目の文はA2→A3のエッジを追加しています。A2→A3の矢印がA1→A2とA1→A3の位置関係に影響を与えないようにconstraint='false'
に設定して、レイアウト制約を無効化しています。
最後に、画像をカレントディレクトリ(作業ディレクトリ)に出力しています。ファイル名を変更したい場合にはdot.render('output_graph')
のように指定できます。
# 画像を出力
dot.render()
# グラフを表示
dot.view()
生成した画像を画像ビューアなどで自動的に開きたい場合には、dot.view()
の方を使用します。
作成したグラフのDOT言語がほしい場合には、次のコマンドで出力できます。
# グラフを作成するためのDOT言語を標準出力する
print(dot.source)
このサンプルプログラムの場合には以下が得られます。
digraph {
A1 [label="Kin Arthur"]
A2 [label="Sir Bedevere the Wise"]
A3 [label="Sir Lancelot the Brave"]
A1 -> A2
A1 -> A3
A2 -> A3 [constraint=false]
}
GraphvizからDOT言語を直接扱う
GraphvizライブラリからDOT言語を直接扱うこともできます。例えば、DOT言語で書かれた文字列変数を次のように与えることができます。
import graphviz
dot_source = """
digraph G {
A -> B;
B -> C;
C -> A;
}
"""
dot = graphviz.Source(dot_source)
dot.render('graph')
dot.view()
また、DOT言語で記述されたファイルを読み込むこともできます。
import graphviz
# Dotファイルを読み込む
dot = graphviz.Source.from_file('graph.dot')
# グラフを表示
dot.view()
この例では、カレントディレクトリにあるgraph.dot
ファイルを読み込んでいます。
日本語フォントの使用
日本語を使用する場合には、fontname
で日本語に対応しているフォントを指定しなければなりません。
# デフォルトのフォントを指定する場合(例:MSゴシック)
dot.attr('node', fontname='MS Gothic')
dot.attr('edge', fontname='MS Gothic')
# ノードのフォントを個別に指定する場合(例:MSゴシック)
dot.node('A', 'こんにちは', fontname='MS Gothic')
dot.node('B', 'Graphviz', fontname='MS Gothic')
# エッジのフォントを個別に指定する場合(例:MSゴシック)
dot.edge('A', 'B', label='エッジ', fontname='MS Gothic')
フォントが日本語に対応していない場合には、ラベルなどが文字化けします。
ノード作成の主なオプション
Graphvizでは、ノードの形状・色フォント・スタイルなどを細かく設定できます。
形状関連(shape)
ノードの形状はshape
オプションで設定します。
dot.node('A', 'Example', shape='box') # 四角形
数十種類のshape
が使用可能ですが、よく使われるものを以下に分類して紹介します。
まず、一般的なフローチャート向けに使用される基本形状です。
shape | 用途 |
'box' | 長方形(プロセス) |
'ellipse' | 楕円形(開始・終了) |
'circle' | 円形(状態図など) |
'diamond' | ひし形(条件分岐) |
'parallelogram' | 平行四辺形(入力/出力) |
'trapezium' | 台形(特殊な処理) |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', 'Process', shape='box')
dot.node('B', 'Start', shape='ellipse')
dot.node('C', 'State', shape='circle')
dot.node('D', 'Condition?', shape='diamond')
dot.node('E', 'Input/Output', shape='parallelogram')
dot.node('F', 'Special Process', shape='trapezium')
dot.view()
次に、クラス図・データ構造向けの形状です。
shape | 用途 |
'record' | クラス図、データ構造 |
'Mrecord' | マルチレコード(複数区切り) |
'tab' | タブ付きの長方形 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('G', '''{
ClassName |
- attribute1: int \l
- attribute2: string \l
|
+ method1(): void \l
+ method2(): int \l
}''', shape='record')
dot.node('H', '{Module | Function1 | Function2}', shape='Mrecord')
dot.node('I', 'Tabbed Box', shape='tab')
dot.view()
record
は|
でセクションを分け、\l
で左寄せを行います。ラベル中に<ポート名>
を記述すると、エッジの接続先を指定するときに'識別子:ポート名'
という形でそのポート名を使用できます。以下の例ではノードAのClassNameにポート名<pa>をつけて、そこにエッジの始点を接続しています。
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', '''{
<pa> ClassName |
- attribute1: int \l
- attribute2: string \l
|
+ method1(): void \l
+ method2(): int \l
}''', shape='record')
dot.node('B', '''{
ClassName |
- attribute1: int \l
- attribute2: string \l
|
+ method1(): void \l
+ method2(): int \l
}''', shape='record')
dot.edge('A:pa', 'B')
dot.view()
次に、ネットワーク・システム構成図向けの形状です。
shape | 用途 |
'box3d' | 3D風のボックス(サーバー) |
'cylinder' | データベース(円柱) |
'component' | ソフトウェアコンポーネント |
'folder' | フォルダ |
'note' | メモ用 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('J', 'Server', shape='box3d')
dot.node('K', 'Database', shape='cylinder')
dot.node('L', 'Redis Cache', shape='component')
dot.node('M', 'Project Folder', shape='folder')
dot.node('N', 'Documentation', shape='note')
dot.view()
次に、ユーザーインターフェイス向けの形状です。
shape | 用途 |
'oval' | 楕円(ellipse の別名) |
'doublecircle' | ダブルサークル(状態図) |
'plaintext' | 枠なしテキスト |
'square' | 正方形 |
'rect' | 長方形(box の別名) |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('U', 'Final State', shape='doublecircle')
dot.node('V', 'Just Text', shape='plaintext')
dot.node('W', 'Square Node', shape='square')
dot.node('X', 'Rectangle Node', shape='rect')
dot.view()
最後に、それ以外の形状を示します。
shape | 用途 |
'egg' | 卵型(柔らかい楕円) |
'triangle' | 上向き三角形 |
'invtriangle' | 下向き三角形 |
'house' | 家の形 |
'invhouse' | 逆さの家 |
'pentagon' | 五角形 |
'hexagon' | 六角形 |
'septagon' | 七角形 |
'octagon' | 八角形 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', 'Egg Shape', shape='egg')
dot.node('B', 'Up Triangle', shape='triangle')
dot.node('C', 'Down Triangle', shape='invtriangle')
dot.node('D', 'House', shape='house')
dot.node('E', 'Inverted House', shape='invhouse')
dot.node('F', 'Pentagon', shape='pentagon')
dot.node('G', 'Hexagon', shape='hexagon')
dot.node('H', 'Septagon', shape='septagon')
dot.node('I', 'Octagon', shape='octagon')
dot.view()
スタイル
スタイルではノードの背景と枠線を変更します。スタイルを変更するにはstyle
オプションを指定します。
dot.node('A', 'Filled Node', style='filled')
style | 説明 |
'filled' | ノードの背景を塗りつぶす |
'dashed' | 枠線を破線にする |
'dotted' | 枠線を点線にする |
'bold' | 枠線を太くする |
'rounded' | 角を丸くする(box のみ有効) |
'solid' | 通常の枠線(デフォルト) |
'invisible' | ノードを非表示にする |
'wedged' | 背景を複数色のくさび型にする |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', 'Filled Node', style='filled', fillcolor='lightblue')
dot.node('B', 'Dashed Border', style='dashed')
dot.node('C', 'Dotted Border', style='dotted')
dot.node('D', 'Bold Border', style='bold')
dot.node('E', 'Rounded Box', shape='box', style='rounded')
dot.node('F', 'Solid Border', style='solid')
dot.node('G', 'Invisible', style='invisible')
dot.node('H', 'Wedged', style='wedged', fillcolor='red:blue:green')
dot.view()
色
ノードの枠線、背景、文字の色を指定できます。
属性 | 説明 |
color | ノードの枠線の色 |
fillcolor | ノードの背景色(style='filled' が必要) |
fontcolor | 文字の色 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', 'Red Border', color='red')
dot.node('B', 'Green Fill', style='filled', fillcolor='green')
dot.node('C', 'Blue Text', fontcolor='blue')
dot.view()
色は'red'
などの名前、あるいは、RGBの順で16進数で指定します(例えば、緑の場合は#00FF00
)。
フォントのサイズと種類
フォントの種類とサイズを指定できます。
属性 | 説明 |
fontsize | 文字のサイズ |
fontname | フォントの種類 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', 'Big Font', fontsize='20')
dot.node('B', 'Courier Font', fontname='Courier')
dot.node('C', 'Arial Font', fontname='Arial')
dot.view()
ノードのサイズとマージン、外部ラベル
ノードのサイズやテキストの余白を調整できます。また、ノードの外部にラベルを追加できます。
属性 | 説明 |
width | ノードの幅 |
height | ノードの高さ |
margin | テキストの周囲の余白 |
xlabel | ノードの外部ラベル |
import graphviz
dot = graphviz.Digraph(format='png')
dot.node('A', 'Wide Node', width='2')
dot.node('B', 'Tall Node', height='1.5')
dot.node('C', 'With Margin', margin='0.2')
dot.node('D', 'Normal Label', xlabel='Extra Label')
dot.view()
ツールチップとリンク(SVG出力時)
SVG出力時に、マウスオーバーで表示されるツールチップやクリックするとリンク先に移動するノードを作成できます。
属性 | 説明 |
tooltip | マウスオーバー時に表示される説明テキスト |
URL | クリックしたときのリンク先のアドレス |
import graphviz
dot = graphviz.Digraph(format='svg')
dot.node('A', 'Hover me!', tooltip='This is a tooltip')
dot.node('B', 'Click Me', URL='https://www.google.com')
dot.view()
エッジ作成の主なオプション
Graphvizでは、矢印の種類や線のスタイル、色、ラベルなどを変更できます。
矢印のスタイル
エッジの始点(arrowtail
)と終点(arrowhead
)の矢印の種類を変更できます。矢印をつける位置はdir
で指定します。
属性 | |
arrowhead | 終点の矢印の形状を指定 |
arrowtail | 始点の矢印の形状を指定 |
dir | 矢印のつける位置を指定 終点( 'normal' )、始点('back' )、両方('both' )から選択 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.edge('A', 'B', label='Normal Arrow') # デフォルト
dot.edge('C', 'D', label='Back Arrow', dir='back')
dot.edge('E', 'F', label='Both Arrow', dir='both')
dot.edge('G', 'H', label='Box Head', arrowhead='box', dir='forward')
dot.edge('I', 'J', label='Dot Tail', arrowtail='dot', dir='back')
dot.edge('K', 'L', label='No Arrow', arrowhead='none')
dot.view()
矢印の形状として主に指定できるものを示します。
値 | 用途 |
'normal' | デフォルトの矢印 |
'none' | 矢印なし |
'dot' | 丸い矢印 |
'diamond' | ダイヤモンドの矢印 |
'crow' | 三つ又の逆矢印 |
'tee' | T型の矢印 |
'vee' | 逆三角形の矢印 |
'box' | ボックス型の矢印 |
'curve' | 曲線の矢印 |
'icurve' | 逆向き曲線の矢印 |
'inv' | 逆矢印 |
'lcurve' | 左曲がり矢印 |
'rcurve' | 右曲がり矢印 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.edge('A', 'B', label='Nornal', arrowhead='normal', dir='forward')
dot.edge('C', 'D', label='None', arrowhead='none', dir='forward')
dot.edge('E', 'F', label='Dot', arrowhead='dot', dir='forward')
dot.edge('G', 'H', label='Diamond', arrowhead='diamond', dir='forward')
dot.edge('I', 'J', label='Crow', arrowhead='crow', dir='forward')
dot.edge('K', 'L', label='Tee', arrowhead='tee', dir='forward')
dot.edge('M', 'N', label='Vee', arrowhead='vee', dir='forward')
dot.edge('O', 'P', label='Box', arrowhead='box', dir='forward')
dot.edge('Q', 'R', label='Curve', arrowhead='curve', dir='forward')
dot.edge('S', 'T', label='ICurve', arrowhead='icurve', dir='forward')
dot.edge('U', 'V', label='Inv', arrowhead='inv', dir='forward')
dot.edge('W', 'X', label='LCurve', arrowhead='lcurve', dir='forward')
dot.edge('Y', 'Z', label='RCurve', arrowhead='rcurve', dir='forward')
dot.view()
'odiamond'
のように接頭語にoをつけると、矢印の塗りつぶしをなくせます。
また、'lcurve'
や'rcurve'
のように接頭語にl, rをつけると、その方向の矢印がクリップされます。
線の種類
style
属性を用いてエッジの線の種類を変更できます。
値 | 説明 |
'solid' | 通常の線(デフォルト) |
'dashed' | 破線 |
'dotted' | 点線 |
'bold' | 太線 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.edge('A', 'B', label='Solid', style='solid')
dot.edge('C', 'D', label='Dashed', style = 'dashed')
dot.edge('E', 'F', label='Dotted', style = 'dotted')
dot.edge('G', 'H', label='Bold', style = 'bold')
dot.view()
色と太さの変更
エッジの色と円の太さを変更できます。
属性 | 説明 |
color | 色を指定 |
penwidth | 線の太さを指定 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.edge('A', 'B', label='Red Edge', color='red')
dot.edge('C', 'D', label='Blue Edge', color='blue')
dot.edge('E', 'F', label='Gradient Edge', color='red:blue')
dot.edge('G', 'H', label='Thin Line', penwidth='0.5')
dot.edge('I', 'J', label='Thick Line', penwidth='3.0')
dot.view()
色の指定はRGBの順に16進数で指定することもできます(例えば、緑の場合は'#00FF00'
)。
ラベルの変更
ラベルのテキストやフォント、色を変更することができます。
属性 | 説明 |
label | エッジの中央に表示するテキスト |
headlabel | エッジの終点に表示するラベル |
taillabel | エッジの始点に表示するラベル |
labeldistance | ラベルを矢印からどれだけ離すか (headlabelとtaillabelのみ有効) |
labelangle | ラベル位置の回転角度(0°~90°) (headlabelとtaillabelのみ有効) |
fontname | フォントの種類 |
fontsize | フォントのサイズ |
fontcolor | フォントの色 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.edge('A', 'B', headlabel='Head Label', labeldistance='1.0', labelangle='30')
dot.edge('C', 'D', taillabel='Tail Label', labeldistance='1.0', labelangle='30')
dot.edge('E', 'F', label='Large Font (25pt)', fontsize='25')
dot.edge('G', 'H', label='Small Font (10pt)', fontsize='10')
dot.edge('I', 'J', label='Blue Text', fontcolor='blue')
dot.edge('K', 'L', label='Green Text', fontcolor='green')
dot.view()
エッジの接続位置
エッジの接続位置を変更できます。接続位置は'識別子:ポート名'
という形で指定します。使用できるポート名の一覧を以下に示します。
ポート名 | 説明 |
n | 上 |
ne | 右上 |
e | 右 |
se | 右下 |
s | 下 |
sw | 左下 |
w | 左 |
nw | 左上 |
c | 中央 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.edge('A:n', 'B:ne')
dot.view()
デフォルトの変更
ノードやエッジのデフォルトの設定を変更できます。デフォルトの設定にはattr
を使用します。
import graphviz
dot = graphviz.Digraph(format='png')
# ノードのデフォルト設定
dot.attr('node', shape='ellipse', style='filled', fillcolor='yellow', fontname='Courier', fontsize='16')
# エッジのデフォルト設定
dot.attr('edge', color='green', penwidth='2.5', fontcolor='black', fontsize='14')
# グラフ全体のデフォルト設定
dot.attr(rankdir='TB', bgcolor='lightblue')
# ノードとエッジを作成
dot.node('A', 'Start')
dot.node('B', 'Decision')
dot.node('C', 'End')
dot.edge('A', 'B', label='Proceed?')
dot.edge('B', 'C', label='Finish')
dot.view()
レイアウトの変更
レイアウトの方向
rankdir
を用いることで、レイアウトの方向を変更できます。例えば、'BT'
を選択するとノードが下から上に向かって順に配置されます。
rankdir の値 | レイアウト方向 |
TB | 上から下 |
BT | 下から上 |
LR | 左から右 |
RL | 右から左 |
import graphviz
dot = graphviz.Digraph(format='png')
dot.attr(rankdir='BT')
dot.edge('A', 'B')
dot.view()
dot.edge
のオプションにconstraint='false'
を設定すると、そのエッジはレイアウトのルールの対象外になります。
サブグラフによるレイアウトの制御
subgraph
を使うと、ノードのグループ化やレイアウトの制御ができます。
subgraph
に対してattr
を使用することで、subgraph
内のレイアウトや色を設定しています。
import graphviz
dot = graphviz.Digraph(format='png', graph_attr={'rankdir': 'TB'}) # 上から下
# ランク1(ルートノード)
with dot.subgraph(name='cluster_rank1') as rank1:
rank1.attr(label='Rank 1', color='black', style='filled', fillcolor='lightgray')
rank1.node('A', 'Root')
# ランク2
with dot.subgraph(name='cluster_rank2') as rank2:
rank2.attr(label='Rank 2', color='black', style='filled', fillcolor='lightgray')
rank2.attr(rank='same') # 横並びにする
rank2.node('B1')
rank2.node('B2')
# ランク3
with dot.subgraph(name='cluster_rank3') as rank3:
rank3.attr(label='Rank 3', color='black', style='filled', fillcolor='lightgray')
rank3.attr(rank='same') # 横並びにする
rank3.node('C1')
rank3.node('C2')
rank3.node('C3')
# ランク4
with dot.subgraph(name='cluster_rank4') as rank4:
rank4.attr(label='Rank 4', color='black', style='filled', fillcolor='lightgray')
rank4.attr(rank='same') # 横並びにする
rank4.node('D1')
rank4.node('D2')
rank4.node('D3')
rank4.node('D4')
# ランク5(最下層)
with dot.subgraph(name='cluster_rank5') as rank5:
rank5.attr(label='Rank 5', color='black', style='filled', fillcolor='lightgray')
rank5.attr(rank='same') # 横並びにする
rank5.node('E1')
rank5.node('E2')
# エッジの追加(ツリー構造)
dot.edge('A', 'B1')
dot.edge('A', 'B2')
dot.edge('B1', 'C1')
dot.edge('B1', 'C2')
dot.edge('B2', 'C3')
dot.edge('C1', 'D1')
dot.edge('C1', 'D2')
dot.edge('C2', 'D3')
dot.edge('C3', 'D4')
dot.edge('D1', 'E1')
dot.edge('D3', 'E2')
dot.view()
レイアウトエンジンの変更
Graphvizのレイアウトエンジンには、用途に応じた6種類のエンジンがあります。
エンジン名 | 特徴 | 主な用途 |
dot | 階層レイアウト | ツリー構造・フローチャート |
neato | バランスよく配置 | ネットワーク・関係図 |
fdp | neatoの高速版 | グラフ理論・クラスタ分析 |
sfdp | 大規模データ対応(fdpの拡張) | 大量のノードを美しく配置 |
twopi | 中心から放射状に配置 | 組織図・階層構造 |
circo | 環状に配置(ループ関係を可視化) | ループ構造・円環の関係性 |
osage | 配列状に配置 | 関係のあるノードをグループ化 |
graphviz.Digraph
またはgraphviz.Graph
のengine
オプションによりレイアウトエンジンを指定できます。それぞれのレイアウトエンジンの例を示します。
dot
の例を示します。
import graphviz
dot = graphviz.Digraph(format='png', engine='dot')
dot.edge('A', 'B')
dot.edge('A', 'C')
dot.edge('B', 'D')
dot.edge('C', 'E')
dot.view()
neato
の例を示します。
import graphviz
dot = graphviz.Graph(format='png', engine='neato')
#dot = graphviz.Graph(format='png', engine='fdp')
#dot = graphviz.Graph(format='png', engine='sfdp')
dot.edge('A', 'B')
dot.edge('A', 'C')
dot.edge('B', 'D')
dot.edge('C', 'E')
dot.edge('D', 'E')
dot.view()
twopi
の例を示します。
import graphviz
dot = graphviz.Digraph(format='png', engine='twopi')
dot.node('A', shape='circle', style='filled', fillcolor='lightblue')
for i in range(1, 6):
dot.node(str(i), shape='circle', style='filled', fillcolor='lightgray')
dot.edge('A', str(i))
dot.view()
circo
の例を示します。
import graphviz
dot = graphviz.Digraph(format='png', engine='circo')
# 駅のノードを環状に配置
stations = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
for i in range(len(stations)):
dot.edge(stations[i], stations[(i + 1) % len(stations)], label=f'Line {i+1}')
# 一部の駅から中央駅へ接続(放射状の接続)
dot.node('Center', 'Main Station', shape='doublecircle', style='filled', fillcolor='yellow')
dot.edge('A', 'Center', label='Express')
dot.edge('D', 'Center', label='Express')
dot.edge('G', 'Center', label='Express')
dot.view()
osage
の例を示します。
import graphviz
dot = graphviz.Digraph(format='png', engine='osage')
dot.node('CEO', 'CEO', shape='box', style='filled', fillcolor='lightblue')
# 営業部門
dot.node('Sales_Head', 'Sales Head', shape='box', style='filled', fillcolor='lightgray')
dot.node('Sales_1', 'Sales Manager A')
dot.node('Sales_2', 'Sales Manager B')
# 技術部門
dot.node('Tech_Head', 'Tech Head', shape='box', style='filled', fillcolor='lightgray')
dot.node('Dev_1', 'Developer A')
dot.node('Dev_2', 'Developer B')
# 人事部門
dot.node('HR_Head', 'HR Head', shape='box', style='filled', fillcolor='lightgray')
dot.node('HR_1', 'HR Manager')
# エッジの設定
dot.edge('CEO', 'Sales_Head')
dot.edge('CEO', 'Tech_Head')
dot.edge('CEO', 'HR_Head')
dot.edge('Sales_Head', 'Sales_1')
dot.edge('Sales_Head', 'Sales_2')
dot.edge('Tech_Head', 'Dev_1')
dot.edge('Tech_Head', 'Dev_2')
dot.edge('HR_Head', 'HR_1')
dot.view()
まとめ
Graphvizを活用すれば、Pythonで手軽に高品質がグラフが作成できます。レイアウトエンジンを上手に選択することで、より見やすく、わかりやすい可視化が可能です。グラフを作図する際の参考になりましたら幸いです。
参考情報
- Graphvizの公式ドキュメント(https://graphviz.org/documentation/)