TECHNOLOGY

Python x Graphvizの基本的な使い方

フローチャートや簡易的な関係図などをWordやPowerPointで作成すると、矢印の長さや枠のサイズを調整するのが意外と面倒だと感じることがあります。Python + Graphvizを使うと、手作業のミスを減らし一貫性のあるグラフを生成できることや、データを変更すればグラフを即座に更新できるなどの利点があります。また、Pythonの条件文と組み合わせることにより、条件に応じてグラフを変更するなども可能になります。この記事では、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バランスよく配置ネットワーク・関係図
fdpneatoの高速版グラフ理論・クラスタ分析
sfdp大規模データ対応(fdpの拡張)大量のノードを美しく配置
twopi中心から放射状に配置組織図・階層構造
circo環状に配置(ループ関係を可視化)ループ構造・円環の関係性
osage配列状に配置関係のあるノードをグループ化

graphviz.Digraphまたはgraphviz.Graphengineオプションによりレイアウトエンジンを指定できます。それぞれのレイアウトエンジンの例を示します。

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で手軽に高品質がグラフが作成できます。レイアウトエンジンを上手に選択することで、より見やすく、わかりやすい可視化が可能です。グラフを作図する際の参考になりましたら幸いです。

参考情報

-TECHNOLOGY
-,