graph-tool チートシート(可視化編)


はじめに

グラフの可視化のツールは様々なものがあるが、graph-toolはその中でも最も強力といっても過言ではないだろう。
いろいろな可視化の方法が実装されているだけでなく、OpenMP化したC++で実装されているのでかなり大きなネットワークでも描画することができる。
例えばこのような可視化ができる。( https://graph-tool.skewed.de/ より )


ここではgraph-toolを用いた可視化について典型的な処理をまとめていく。

reference

動作環境

動作確認環境は以下の通り

  • python 3.9.0
  • graph-tool 2.35
  • numpy, matplotlib

以後のサンプルコードでは、前提条件として以下のモジュールをimportしている。

import graph_tool.all as gt
import numpy as np
import matplotlib.pyplot as plt

またサンプルデータとして以下のものを用いる。(ある小説における名詞と形容詞の隣接関係から構築したネットワーク)

g = gt.collection.data['adjnoun']

Jupyter notebookで実行するかターミナルから実行するか

graph-toolで可視化するコードを実行する場合、jupyter notebookで実行するかターミナルで実行するかに依存して若干挙動が異なる。
可視化するスクリプトをjupyterから実行した場合、ノートブック内にインラインで表示される。

一方でスクリプトをターミナルから実行した場合、interactiveなGUI windowに描画される。ノードをマウスでドラッグ&ドロップして動かしたり、選択したノードとそのエッジをハイライトしたりできる。用途に応じて使い分けたい。

コード

とりあえず描画する

gt.graph_drawメソッドを呼べば良い

gt.graph_draw( g )

ファイル出力する

outputオプションにファイル名を指定する。拡張子に応じてフォーマットを決めてくれる。
pdf, svg, png, jpgなど様々な形式に対応している。

gt.graph_draw(g, output = 'graph.pdf')

pngなどのラスタ形式の画像で画像の大きさを変えたい場合は、output_size オプションを指定する

gt.graph_draw(g, output = 'graph.png', output_size=(1000,1000))

ノードにラベルを表示する

VertexPropertyで指定する文字列を表示するにはvertex_textオプションを指定する。

gt.graph_draw(g, vertex_text = g.vp.label)

ノードの外側に表示したいときはvertex_text_position = 0を指定する。

gt.graph_draw(g, vertex_text = g.vp.label, vertex_text_position = 0)

その他、オプションをいじることでテキストの色やフォントなど細かく調整できる。

gt.graph_draw(g, vertex_text = g.vp.label, vertex_text_position = 0, vertex_font_size = 16, vertex_text_offset = [-1,1], vertex_text_color=(255,0,255,255))

レイアウトを変更する

graph-toolには様々なlayoutアルゴリズムが用意されている。まずレイアウトを計算し、得られた位置情報をgraph_drawの引数に渡す。

pos = gt.radial_tree_layout(g, 0)
gt.graph_draw(g, pos = pos)

ノードやエッジの見た目を次数などの統計量に応じて変更する

ノードやエッジのサイズや色を次数や他のネットワーク統計量に応じて変更することができる。
例えば、次数に応じてノードの大きさを変更するには以下のようにする。

deg = g.degree_property_map("total")
gt.graph_draw(g, vertex_size = deg)

スケールをうまく調整するには gt.prop_to_size メソッドを使うと良い。指定した最小値、最大値になるように適切にスケーリングしてくれる。logスケールにすることもできる。

gt.graph_draw(g, vertex_size = gt.prop_to_size(deg,mi=5,ma=20,log=False) )

工夫すれば他にも幅や色味など色々と変更できる。

deg = g.degree_property_map("total")
ebet = gt.betweenness(g)[1]   # edge betweeness
gt.graph_draw(g,
              vertex_size=gt.prop_to_size(deg,mi=5,ma=20,log=False),
              vertex_fill_color=gt.prop_to_size(deg,log=False),
              vcmap=(matplotlib.cm.inferno, .9),
              vorder=deg,
              edge_color=gt.prop_to_size(ebet),
              eorder=ebet,
              edge_pen_width=gt.prop_to_size(ebet,mi=1,ma=5,log=False),
              ecmap=(matplotlib.cm.bone, .7)
             )