Graphvizとは、AT&T研究所の作ったグラフ描画ソフトである。
ここでのグラフとは棒グラフのグラフではなく、ソーシャルグラフとかのグラフである。
点(ノード)と線(エッジ)で表されるもので、例えば、何らかの状態遷移や、路線図や、ネットワークなどの「関係」の表現に使われる。

もともとオイラーの一筆書きのような経路探索の分野があって、それを視覚的に表現するためのツールとしてこういったソフトがある(たぶん)。
そんな分野はとても手に負えない。
しかし、グラフ描画に注目するだけでも、とても面白いんである。

例えば、ふだん利用する路線の、各駅の関係と乗降数をグラフに書いてみるだけでも、表で見たときは比べ物にならないくらいのインパクトがある。

img これは、京浜急行の駅の繋がりと乗降者数をグラフにしてみたもの。
隣り合う駅は繋ぐし、特急などで途中の駅をすっ飛ばす場合も繋ぐ。
乗降者数に応じて駅の大きさを変えてみた。
(何気なく作ったら一辺が10,000ピクセルを超える巨大画像になったので泣く泣く縮小した。)

そういったわけで、この記事では(Python経由で)graphvizのグラフ描画についてまとめた。

以下、特に指定のないかぎり、グラフと記載があれば、それは上記の意味でのグラフである。

Graphvizについて

手っ取り早くどんなグラフが描けるのかを知りたければこちらのサンプルグラフなどを。

関連のwebsiteは以下のとおり。

Graphviz(公式) http://www.graphviz.org/
Graphviz(wiki) http://ja.wikipedia.org/wiki/Graphviz

Graphvizでは、DOTという形式でグラフを描画する。
しかしDOT形式をそのまま扱うのはちょっと難しい。
そこで他の言語を通して使う。
具体的にはpygraphviz。
PyGraphvizはGraphvizのpythonインタフェースである。

PyGraphvizのインストール

FreeBSD, OS Xでのインストールは確認済みである。
しかし意外や意外、WindowsのActivePythonではPyGraphvizをインストールできない。PyPMにないのである。
素のPythonなら出来るのかもしれないが。

しかし、Graphviz単体ならインストールできる。DOT形式のファイル(以降、DOTファイル)を別マシンからもらえば、WIndows上でもグラフ描画は可能。

FreeBSDでのインストール

portsでもpkgでも、pygraphvizで探せば出てくるのでそれをインストールすればよい。
以下はpkgでの例。
gccを連れてきてダウロードサイズが100MBを超えた。驚いた。
ついでnumpyも入れた。

$ pkg search graphviz
graphviz-2.34.0
py27-graphviz-1.1_1
rubygem-graphviz-1.0.9
trac-graphviz-0.7.4_6
$ sudo pkg install py27-numpy py27-graphviz
Updating repository catalogue
The following 12 packages will be installed:

        Installing mpc: 1.0.1
        Installing gcc-ecj: 4.5
        Installing binutils: 2.23.2
        Installing py27-nose: 1.3.0
        Installing libgd: 2.1.0_1,1
        Installing gcc: 4.6.4
        Installing graphviz: 2.34.0
        Installing blas: 3.4.2_1
        Installing py27-graphviz: 1.1_1
        Installing lapack: 3.4.2_1
        Installing suitesparse: 4.0.2_2
        Installing py27-numpy: 1.7.0_2,1

The installation will require 685 MB more space

110 MB to be downloaded

OS Xでのインストール

graphvizをインストールし、そのあとPython上でpygraphvizをインストールすればよろし。
以下の例ではbrewでgraphvizを、そのあとpipでpygraphvizをインストールしている。

$ brew install graphviz
==> Downloading http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.3
######################################################################## 100.0%
==> Downloading patches
<snip>
==> make install
/usr/local/Cellar/graphviz/2.30.1: 462 files, 10M, built in 3.1 minutes
$

$ pip install pygraphviz
Downloading/unpacking pygraphviz
  Using download cache from /Users/xxx/.pip/cache/https%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fp%2Fpygraphviz%2Fpygraphviz-1.2.tar.gz
  Running setup.py egg_info for package pygraphviz
    Trying pkg-config
    library_path=/usr/local/Cellar/graphviz/2.30.1/lib
    include_path=/usr/local/Cellar/graphviz/2.30.1/include/graphviz
<snip>
    no previously-included directories found matching 'doc/build'
Successfully installed pygraphviz
Cleaning up...
$

Windowsでのインストール(graphvizだけ)

WindowsのActivePythonではpygraphvizが使えない。
素のgraphvizをインストールする。
以下あたりからダウンロードする。

http://www.graphviz.org/Download_windows.php

インストーラがよければmsiを、レジストリを汚したくないならzipをダウンロード。
zipは展開するとreleaseというフォルダが出来る。
リネームしてどこにでも置けばよい。
実行ファイルはbinの下にある。
必要ならパスを通しておく。

実際に使う実行ファイルはdot、circo、neatoあたりでしょう。

pygraphvizインストールの確認

pygraphvizをimportしてみてエラーの出ないことを確認しておこう。
たとえばIDLEで。

Python 2.7.5 (default, Oct 17 2013, 07:35:17)
[GCC 4.2.1 Compatible FreeBSD Clang 3.3 (tags/RELEASE_33/final 183502)] on freebsd10
Type "copyright", "credits" or "license()" for more information.
>>> import pygraphviz
>>>

PyGraphvizを使ってみよう。

基本はここのチュートリアルに沿えばよい。
http://networkx.lanl.gov/pygraphviz/tutorial.html

pygraphvizをimportし、AGraphクラスを作る。

import pygraphviz as pgv
G = pgv.AGraph()

ノードの追加

G.add_node('a')
G.add_node('b')

エッジの追加

G.add_edge('c','d')
G.add_edge('e','f')

そして描画。
layoutを指示すると各ノード、エッジの配置がなされ、drawで画像に書き込める。

G.layout()
G.draw('sample01.png')

dotファイルを書き出すには。

G.write("sample01.dot")

サンプルスクリプト

以下、サンプルスクリプトとその結果つくられるグラフを列挙する。
先述の通りWindowsではpygraphvizが使えない。
Windowsでグラフを描こうとするなら、MacやFreeBSD他、pygraphvizで生成しておいたdotをWindows上のgraphvizで読みこむしかない。
その方法は最後に触れる。

サンプル1

#!/bin/env python

import pygraphviz as pgv

G = pgv.AGraph()

G.add_node('a')
G.add_node('b')

G.add_edge('c','d')
G.add_edge('e','f')

G.layout()
G.draw('sample01.png')

img

サンプル2

ノードの追加は、リストでまとめてできる。

#!/bin/env python

import pygraphviz as pgv

G = pgv.AGraph()

nodelist = ['g','h','i']

G.add_nodes_from(nodelist)

G.add_edge('c','d')
G.add_edge('e','f')

G.layout()
G.draw('sample02.png')

img

サンプル3

同じエッジを二回追加しても変わらない。

#!/bin/env python

import pygraphviz as pgv

G = pgv.AGraph()

nodelist = ['g','h','i']

G.add_nodes_from(nodelist)

G.add_edge('h','i')
G.add_edge('h','i')

G.layout()
G.draw('sample03.png')

img

サンプル4

しかし、最初のクラス作成時にstrict=Falseと指定すれば。

#!/bin/env python

import pygraphviz as pgv

G = pgv.AGraph(strict=False)

nodelist = ['g','h','i']

G.add_nodes_from(nodelist)

G.add_edge('h','i')
G.add_edge('h','i')

G.layout()
G.draw('sample04.png')

img 二本になる。

サンプル5

さらにdirectを指定すれば。

#!/bin/env python

import pygraphviz as pgv

G = pgv.AGraph(strict=False, directed=True)

nodelist = ['g','h','i']

G.add_nodes_from(nodelist)

G.add_edge('h','i')
G.add_edge('h','i')

G.layout()
G.draw('sample05.png')

img 矢印になる。

サンプル6

ここまでは殺風景であったが、色だって形だって変更できる。

#!/bin/env python

import pygraphviz as pgv

G = pgv.AGraph(strict=False, directed=True)

nodelist = ['g','h','i']

G.add_nodes_from(nodelist)

G.add_edge('h','i')
G.add_edge('h','i')

G.layout()
G.draw('sample05.png')

img

参考

ここから先は、以下を参考にして各自素敵なグラフを作ってくれたまえ。
https://github.com/pygraphviz/pygraphviz/blob/master/examples/miles.py

pygraphviz attrの一覧
http://www.graphviz.org/doc/info/attrs.html

Windowsでdotからグラフを描画する。

インストールしたdot, circo, neatoのいずれかに、-Tで出力形式を、-oで出力ファイル名を指定したうえで、dotファイルを与えればよい。

dot -Tpng -o filename.png filename.dot
circo -Tpng -o filename.png filename.dot
neato -Tpng -o filename.png filename.dot