PythonでGraphvizを用いて有向グラフを作成した時のメモ

PythonでGraphvizを用いて有向グラフを作成した時のメモ

# 動作環境
- Windows10 (64bit)
- Python 3.8.1
- Graphviz 2.38


# 環境構築
まずは Windows に Graphviz をインストールする．

[https://graphviz.gitlab.io/_pages/Download/Download_windows.html](https://graphviz.gitlab.io/_pages/Download/Download_windows.html)

今回は msi の方をダウンロードした．
ダウンロード後実行し，ウィザードに従ってインストールする．
インストール後，パスを通しておく．


次に pip で graphviz をインストールする．

```
pip install graphviz
```


# 実際にやってみる
まずは簡単なものから．

##### コードの例
```python
from graphviz import Digraph

graph = Digraph(format="png")

# ノードを追加
graph.node("node1")
graph.node("node2")
graph.node("node3")
graph.node("node4")

# 辺を追加
graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node3", "node4")

# 画像を保存
# 拡張子はいらない
graph.render("image/output")

# 画像を表示
graph.view()
```

##### 出力
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607246/b803a950-8774-41c3-1681-dd3337ebf085.png)


##### コードの説明
```python
from graphviz import Digraph

graph = Digraph(format="png")
```

有向グラフを作成するため，Digraph をインポートする．
png の他に，pdf や svg などでも出力できる．


```python
# ノードを追加
graph.node("node1")
graph.node("node2")
graph.node("node3")
graph.node("node4")
```

ノードを作成する．与えた引数がノードの中に描かれる．


```python
# 辺を追加
graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node3", "node4")
```

辺を作成する．第1引数→第2引数の向きに矢印が付く．

以下のように，ノードを作成していなくてもここで指定すれば新たにノードが作成される．

```python
# 辺を追加
graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node3", "node4")
# 作成していないノードを指定
graph.edge("A", "B")
```

出力は以下のようになる．
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607246/bb390193-f987-9483-aa58-202691c9fbe1.png)


# グラフの見た目を変える
ノードの形状や色を変えることができる．

### 形状の変更

##### コードの例
```python
from graphviz import Digraph

graph = Digraph(format="png")

# ノードを追加
graph.attr("node", shape="square") # 形を正方形にする
graph.node("node1")
graph.node("node2")

graph.attr("node", shape="star") # 形を星形にする
graph.node("node3")
graph.node("node4")

graph.node("node5", shape="circle") # 個別に設定可能
graph.node("node6")

# 辺を追加
graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node3", "node4")
graph.edge("node4", "node5")
graph.edge("node4", "node6")

# 画像を保存
# 拡張子はいらない
graph.render("image/output2")

# 画像を表示
graph.view()
```

##### 出力
![output2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607246/049b90c2-9b76-99ee-30dd-545ce76cd6f0.png)


##### コードの説明
```python
# ノードを追加
graph.attr("node", shape="square") # 形を正方形にする
graph.node("node1")
graph.node("node2")

graph.attr("node", shape="star") # 形を星形にする
graph.node("node3")
graph.node("node4")

graph.node("node5", shape="circle") # 個別に設定可能
graph.node("node6")
```

attr メソッドを用いるとすべてのノードの設定を変更できる．

`shape="（形）"`とすると形を指定できる．

ノードの作成時に形を指定すると，そのノードの設定のみを変更できる．


### 色の変更

##### コードの例
```python
from graphviz import Digraph

graph = Digraph(format="png")

# 見た目の設定
graph.attr("node", style="filled", fillcolor="black", color="red") # ノードの色設定
graph.attr("edge", color="cyan") # 辺の色設定

# ノードを追加
graph.node("node1", style="filled", fillcolor="palegreen", fontcolor="blue")
graph.node("node2", style="filled", fillcolor="yellow")
graph.node("node3", fontcolor="magenta")
graph.node("node4", style="filled", fillcolor="#808080")
graph.node("node5", fontcolor="white")


# 辺を追加
graph.edge("node1", "node2")
graph.edge("node1", "node3")
graph.edge("node2", "node4")
graph.edge("node3", "node4")
graph.edge("node3", "node5")

# 画像を保存
# 拡張子はいらない
graph.render("image/output3")

# 画像を表示
graph.view()
```

##### 出力
![output3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607246/d07d7d79-f9c2-d617-d630-35d1dd26f513.png)



##### コードの説明
```python
# 見た目の設定
graph.attr("node", style="filled", fillcolor="black", color="red") # ノードの色設定
graph.attr("edge", color="cyan") # 辺の色設定

# ノードを追加
graph.node("node1", style="filled", fillcolor="palegreen", fontcolor="blue")
graph.node("node2", style="filled", fillcolor="yellow")
graph.node("node3", fontcolor="magenta")
graph.node("node4", style="filled", fillcolor="#808080")
graph.node("node5", fontcolor="white")
```

形を変えた時のように，attr メソッドを用いることで全体の設定をすることができる．第1引数を`"node"`や`"edge"`とすることで，ノードや辺の設定ができる．

塗りつぶす場合は`style="filled"`，`fillcolor="（色）"`とする．
文字の色を変更する場合は`fontcolor="（色）"`とする．
色はカラーコードで指定することもできる．

ノードを作成するときに個別に設定することもできる．


# 参考
[Python上でGraphvizを使って綺麗なグラフを描く](https://programgenjin.hatenablog.com/entry/2019/02/26/075121)