Dashを利用した動的なネットワーク図作成

# 目次
1.データ作成
2.networkxを利用したネットワーク図作成（html出力）
3.Dashを利用した動的ネットワーク図
3.1.ネットワークの作成
3.2.動的にするためのコード

### 必要なライブラリをインポート

```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from pyvis.network import Network
import random
import dash
import visdcc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input,Output,State
```

### 作成するに至った経緯
システム構築のお仕事をしており、テーブルの多さとバッチ処理の多さにより、どのテーブルとバッチ処理が結びついているのかがわからず、障害時の対応が遅くなる。
そのためネットワーク図の作成を考えた。
テーブル数が多いため、静的なNW図だと文字が潰れる・探すのに時間がかかることを考えて動的なNW図作成を試みた。


# 1.データ作成
ダミーデータを作成する。
```python
node_list=[]
random.seed(0)
node_nomber=50 #何個線を引くか
edge_nomber=30 #何個点を作るか
for i in range(node_nomber):
    r_,l_=random.sample(range(edge_nomber),2)
    node_list.append((str(r_),str(l_)))　　#今後テーブル名を扱いため文字列に変換
node_list #[('3','12),(),(),....,()] 

orig_nodes=[] #タプル型の数字をこのリストに格納
for i in range(len(node_list)):
    orig_nodes.append(node_list[i][0])
    orig_nodes.append(node_list[i][1])
    
    
edges=[]
nodes=[]
for i in sorted(set(orig_nodes),key=float):
    nodes.append({'id':i,'label':i}) #Dash時に使用しやすいために変形
    
    
for i in set(node_list):
    edges.append({'from':i[0],'to':i[1]}) #Dash時に使用しやすいために変形
    
```

# 2.networkxを利用したネットワーク図作成（html出力）
[networkx](https://networkx.org/)を使用したネットワーク図を作成。

```python
G = nx.Graph() #グラフの作成
G.add_edges_from(node_list) #edgeをもとにnodeとnodeを結んでくれる
net=Network(notebook=True)
net.from_nx(G)
net.show('exsample.html')　#出力
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/72c83b9a-7df4-91bf-c1e2-10cc1381d60d.png)


# 3.Dashを利用した動的ネットワーク図
[Dash](https://dash.plotly.com/)を利用して動的なネットワーク図を作成する。

## 3.1.ネットワークの作成
```python
nodes_op=[{'label':'Full(時間がかかります)','value':'full'}] #動的に動かすためのオプションに利用する。
for i in nodes: 
    nodes_op.append({'label':i['id'],'value':i['label']})　#ノードオプションに選択させるノードを格納

app=dash.Dash()
app.layout=html.Div([html.H1('Network'),
                    html.Div([dcc.Dropdown(id='node',options=nodes_op,value='full')]),
    visdcc.Network(id='net',data={'nodes':nodes,'edges':edges},
                   options=dict(height='600px',width='100%'))])
                   #Dropdwonにノードオプションを表示させる。
                   #作成したノード、edgeをNetworkに渡す。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/b4924084-c17d-6c63-2027-ecb019a2ef3d.png)

動的ではなく、全体のグラフとドロップダウンだけが表示される。ドロップダウンを選んでも何も起きない。

## 3.2.動的にするためのコード
callbackを利用して動的なネットワーク図を作成
```python
#出力はネットワーク図とネットワークの元データ（data）
#入力はノードオプションの値
@app.callback(
    Output("net", 'data'),
    Input('node','value')) 
    
def myfun(x):
    edges_=[]
    nodes_op_=[]
    if x=='full':
        nodes_=nodes
        edges_=edges
    else:
        for i in edges:
            for j in i.values():
                if str(j)== x:
                    edges_.append(i)
        for i in edges_:
            nodes_op_.append(i['from'])
            nodes_op_.append(i['to'])
        nodes_=[]
        for i in set(nodes_op_):
            nodes_.append({'id':i,'label':i})
    r_={'nodes':nodes_,'edges':edges_}
    
    return r_

app.run_server(mode="inline",debug=True)
```

動的なネットワークが作成。
２を選んだ場合は隣接するノードが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/64671ded-48e5-cc9f-c1da-1117ae5d4900.png)


以上