・お題:先日、networkxを使ってエッジリストからネットワーク図を描いてみた。エッジが見づらいことがあったので、インタラクティブにグラフを動かせるようにしたい。
・調べてみると、pyvisというライブラリでインタラクティブなネットワークグラフを描けるらしい。さっそく使ってみる。
・pyvisのインストールは済んでいるとする。
・まずはデータを準備する。先日と全く同じでOK。
import pandas as pd
df=pd.DataFrame({"from":["A","A","A","B"],
"to":["B","C","D","C"],
"weight":[4,2,0.5,1]})
・表のうち、fromをsource、toをtargetとして、networkxのグラフに取り込む。
import networkx as nx
G = nx.from_pandas_edgelist(df,source="from", target="to")
・次に、これをpyvisに取り込む。
from pyvis.network import Network
vis_g = Network()
vis_g.from_nx(G)
・これだけでもグラフを作成することはできる。コードを実行すると、ワーキングディレクトリにhtmlが保存された。これを開くと確かにノードを引っ張るとぷるんぷるんグラフが動いて楽しいが、なんだかとても簡素な印象を受ける。ここからちょっと工夫したい。
vis_g.show("test1.html")
・それぞれの属性がどういう風に入っているのか確認してみた。それぞれのノードとエッジは辞書になっており、属性を一つ一つ指定できるらしい。ということは、この辞書を書き換えれば表示も変えられるはず。。
vis_g.nodes
[{'color': '#97c2fc', 'size': 10, 'id': 'A', 'label': 'A', 'shape': 'dot'},
{'color': '#97c2fc', 'size': 10, 'id': 'B', 'label': 'B', 'shape': 'dot'},
{'color': '#97c2fc', 'size': 10, 'id': 'C', 'label': 'C', 'shape': 'dot'},
{'color': '#97c2fc', 'size': 10, 'id': 'D', 'label': 'D', 'shape': 'dot'}]
vis_g.edges
[{'width': 1, 'from': 'A', 'to': 'B'},
{'width': 1, 'from': 'A', 'to': 'C'},
{'width': 1, 'from': 'A', 'to': 'D'},
{'width': 1, 'from': 'B', 'to': 'C'}]
・ノードの大きさと色をdegree、エッジの太さをweightから持ってきたい。それぞれのリストを作成する。
sizes = [n*10 for n in list(dict(nx.degree(G)).values())]#ノードの大きさ
from sklearn.preprocessing import minmax_scale
colors=minmax_scale(list(dict(nx.degree(G)).values()))#色を0-1で表した。
import matplotlib.pyplot as plt
from matplotlib.colors import rgb2hex
cmap = plt.get_cmap("cool")
colorcodes=[rgb2hex(cmap(n)) for n in colors]#pyvisでcolor mapの設定方法が分からなかったので、カラーコードに変換して色名とする。
・これで、ノードの大きさのリスト(sizes)とノードの色のリスト(colorcodes)は以下のようになった。
sizes
[30, 20, 20, 10]
colorcodes
['#ff00ff', '#807fff', '#807fff', '#00ffff']
・次に、これらをノードとエッジの属性に放り込む。
for n in range(len(vis_g.nodes)):
vis_g.nodes[n]["size"]=sizes[n]
vis_g.nodes[n]["color"]=colorcodes[n]
for n in range(len(vis_g.edges)):
vis_g.edges[n]["width"]=df["weight"][n]
・これで、グラフの属性が書き換わったことになるので、図示してみる。
vis_g.show("test2.html")
・もちろんこれもぷるんぷるん動かせる。
・もっとササっとできるやり方がありそうな気がするが、一応目的を達成することはできた。
おわり。