0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PythonとGraphvizでグラフを描く_2

Posted at

前回までのおさらい

前回ではコミックの登場人物を題材に有向グラフを描いてみました。
今回はこのグラフをより詳しくしていきます。

image.png

とりあえずノードを増やす

example2.py
import graphviz

dot = graphviz.Digraph(format= 'png', 
comment = "今世は当主になります ~2話まで 人物相関図")
dot.attr('node', fontname = 'Meiryo UI')
dot.attr('edge', fontname = 'Meiryo UI')

dot.node('L', 'ルーラック・ロンバルディ\n現当主')

dot.node('F', 'フィレンティア・ロンバルディ\n主人公')
dot.node('G', 'ギャラハン・ロンバルディ')
dot.node('E', 'フィレンティアの母')

dot.node('La', 'ローレルズ・ロンバルディ')

dot.node('B', 'ビエーゼ・ロンバルディ')
dot.node('BS', 'セラル・ロンバルディ')
dot.node('R', 'ラビニ・アンゲナス\n皇后')
dot.node('S1', '第1王子')
dot.node('S2', '第2王子')

dot.edge('L', 'G', label = '三男')
dot.edge('L', 'B', label = '長男')
dot.edge('F', 'G', label = '')
dot.edge('F', 'E', label = '')

dot.edge('B', 'BS', '')
dot.edge('BS', 'R', 'いとこ')
dot.edge('R', 'S1', '息子')
dot.edge('B', 'S1', '支持')

dot.edge('F', 'S2', '支援したい')
dot.edge('F', 'L', '次期当主になりたい')

dot.render('./example2.gv', view=True)

example2.gv.png

とりあえずこれで2話時点までで分かる人物相関図が出来ました。しかし、いくつか改善したい点があります。

改善点

  • 注目させたいノードのスタイルを変えたい
  • 全体的な見せ方を変えたい
  • いとこのエッジを双方向にしたい
  • 勢力ごとに見た目を変えたい

ノードのスタイルを変えたい

ノードのスタイルを変えたい時はshapeを変更することで出来ます。主人公のノードを変えてみます。

dot.node('F', 'フィレンティア・ロンバルディ\n主人公', shape='doubleoctagon')

image.png

図のように二重線の八角形に出来ました。
ほかに使えるものはこちらで確認できます。

全体的な見せ方を変えたい

グラフの見せ方、つまりどのようにノードを配置するかなどはレイアウトエンジンを変更することで実現可能です。
デフォルトでは dot が指定されており、これは階層型のグラフの表現に適しています。
小説や漫画の登場人物紹介には適しているとは言いがたいですね。
これを変えてみましょう。

dot = graphviz.Digraph(format= 'png', 
engine='circo',
comment = "今世は当主になります ~2話まで 人物相関図")

image.png

engineにはほかにも

dot(デフォルト), neato, twopi, circo, fdp, osage, patchwork, sfdp があります。
今回は詳しく説明しません。

いとこのエッジを双方向にしたい

セラルからラビニに伸びているいとこのエッジの矢印を双方向にします。これはedgeのdir属性によって実現できます。

dot.edge('BS', 'R', 'いとこ', dir='both')

image.png

bothをnoneにすれば矢印は消えます。
backにすれば矢印の向きが逆になります。
省略時のデフォルトはforwardです。

勢力ごとに見た目を変えたい

このような場合はGraph, Digraphオブジェクトのsubgraph()メソッドを用いて行います。
engineがcircoのままですと背景色が意図した通りに変わらなかったためdotに戻しています。

import graphviz

dot = graphviz.Digraph(format= 'png', 
comment = "今世は当主になります ~2話まで 人物相関図")
dot.attr('node', fontname = 'Meiryo UI')
dot.attr('edge', fontname = 'Meiryo UI')


dot.node('L', 'ルーラック・ロンバルディ\n現当主')

dot.node('F', 'フィレンティア・ロンバルディ\n主人公', shape='doubleoctagon')
dot.node('G', 'ギャラハン・ロンバルディ')
dot.node('E', 'フィレンティアの母')

dot.node('La', 'ローレルズ・ロンバルディ')


dot.node('S2', '第2王子')

dot.edge('L', 'G', label = '三男')

dot.edge('F', 'G', label = '')
dot.edge('F', 'E', label = '')


dot.edge('F', 'S2', '支援したい')
dot.edge('F', 'L', '次期当主になりたい')
dot.edge('L', 'B', '息子')

empress = graphviz.Digraph(name='cluster_empress', node_attr={'shape': 'box'})

empress.attr(style='filled', color='darkorchid1')

empress.node('B', 'ビエーゼ・ロンバルディ')
empress.node('BS', 'セラル・ロンバルディ')
empress.node('R', 'ラビニ・アンゲナス\n皇后')
empress.node('S1', '第1王子')
empress.edge('B', 'BS', '')
empress.edge('BS', 'R', 'いとこ', dir='back')
empress.edge('R', 'S1', '息子')
empress.edge('B', 'S1', '支持')
empress.attr(label='皇后派')
empress.attr('graph', fontname = 'Meiryo UI')

dot.subgraph(empress)
dot.render('./example2.gv', view=True)

image.png

イメージとしては親になるdotオブジェクトに対して別な有向グラフオブジェクトempressを用意して、そこに関係者のノードとエッジを入れ込んでいます。
皇后派のノードは背景色を紫にして、ノードの形も長方形にしています。
グラフやノードの背景色は自由に変更可能です。
色はこちらから探せます

では今回はここまで

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?