この記事では、以下のような点の集合に対して、特定条件のもと相互関係を可視化する方法について考えていきます。

目次
ネットワーク可視化の基礎
networkxというモジュールを使用して、グラフを可視化します。
fig = plt.figure()
G = nx.Graph()
G.add_nodes_from(["A", "B", "C", "D", "E", "F"])
G.add_edges_from([("A", "B"), ("B", "C"), ("B", "F"),("C", "D"), ("C", "E"), ("C", "F"), ("B", "F")])
nx.draw(G, with_labels=True, node_color = "red", edge_color = "gray", node_size = 300, width = 1)
plt.savefig("a.png",dpi = 500)これを利用して上記の点の集合を可視化していきます。
データの加工
csvファイルからデータを抽出して、ndarrayに変換するところまでを一つのクラスにします。
このとき、エクセル上では左下半分を埋めていないため、転置行列を使用してデータを補完します。
class Data:
def __init__(self,file) -> None:
fp = open(file)
self.lines = [fp.readlines() for i in range(len([None for i in open(file,"rb")]))]
self.n = len(self.lines)-1
self.arr = np.array([[int(0) if i == "" else int(i) for i in self.lines[0][j].split(",")[1:]] for j in range(1,self.n)])
self.arr = np.append(self.arr, np.array([0 for i in range(self.n)]).reshape(1, self.n), axis=0)
self.Pn = [i.replace("\n","") for i in self.lines[0][0].split(",")[1:]]
self.arr += np.transpose(self.arr)
pass
def get_array(self):
return self.arr試しに、取得したデータを出力してみます。
>>>self.arr
[[ 0 15 20 60 20 7 10 25 11 8]
[15 0 25 45 40 15 15 28 23 5]
[20 25 0 15 30 20 20 30 8 16]
[60 45 15 0 5 1 25 12 4 27]
[20 40 30 5 0 1 40 27 25 5]
[ 7 15 20 1 1 0 20 8 20 4]
[10 15 20 25 40 20 0 10 15 24]
[25 28 30 12 27 8 10 0 12 28]
[11 23 8 4 25 20 15 12 0 30]
[ 8 5 16 27 5 4 24 28 30 0]]点クラス
それぞれの点が保持できる情報を定義します。
class Pn:
def __init__(self,name,next) -> None:
self.name = name
self.next = next
def __repr__(self) -> str:
return "{}".format(self.next)
def get_name(self):
return self.name
def get_next(self):
return self.nextグラフクラス
上記で作成したデータを保持したクラスをオーバーライドして、ネットワーククラスを作成します。
ループ中に条件分岐することでノード同士の到達時間に応じて接続するかどうかを決めることができます。
class Graph(Data):
def __init__(self, file) -> None:
self.fig = plt.figure()
self.G = nx.Graph()
super().__init__(file)
self.G.add_nodes_from(self.Pn)
print(self.arr)
self.P = [Pn(self.Pn[i],[f"P{j+1}" for j in range(self.n) if 0<self.arr[i][j]<15 ])for i in range(self.n)]
print(self.P[1])
def draw(self) -> None:
nx.draw(self.G, with_labels=True,node_color = "steelblue", edge_color = "black", node_size = 500, width = 3)
def show(self) -> None:
plt.show()
def save(self,name,dpi = 500) -> None:
self.fig.savefig(name,dpi = dpi)
def set_edges(self) -> None:
self.G.add_edges_from([(i,j) for i in self.Pn for j in self.P[int(i[1:])-1].get_next()])コード全体像
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
class Pn:
def __init__(self,name,next) -> None:
self.name = name
self.next = next
def __repr__(self) -> str:
return "{}".format(self.next)
def get_name(self):
return self.name
def get_next(self):
return self.next
class Data:
def __init__(self,file) -> None:
fp = open(file)
self.lines = [fp.readlines() for i in range(len([None for i in open(file,"rb")]))]
self.n = len(self.lines)-1
self.arr = np.array([[int(0) if i == "" else int(i) for i in self.lines[0][j].split(",")[1:]] for j in range(1,self.n)])
self.arr = np.append(self.arr, np.array([0 for i in range(self.n)]).reshape(1, self.n), axis=0)
self.Pn = [i.replace("\n","") for i in self.lines[0][0].split(",")[1:]]
self.arr += np.transpose(self.arr)
pass
def get_array(self):
return self.arr
class Graph(Data):
def __init__(self, file) -> None:
self.fig = plt.figure()
self.G = nx.Graph()
super().__init__(file)
self.G.add_nodes_from(self.Pn)
print(self.arr)
self.lim = 8
self.P = [Pn(self.Pn[i],[f"P{j+1}" for j in range(self.n) if 0<self.arr[i][j]<self.lim ])for i in range(self.n)]
def draw(self) -> None:
nx.draw(self.G, with_labels=True,node_color = "red", edge_color = "black", node_size = 300, width = 2,font_size = 8)
def show(self) -> None:
plt.show()
def save(self,name,dpi = 500) -> None:
self.fig.savefig(name,dpi = dpi)
def set_edges(self) -> None:
self.G.add_edges_from([(i,j) for i in self.Pn for j in self.P[int(i[1:])-1].get_next()])
graph = Graph("Book1.csv")
graph.set_edges()
graph.draw()
graph.save("result.png")
実行結果
graph = Graph("Book1.csv")
graph.set_edges()
graph.draw()
graph.save("result.png")
このグラフには方向の情報がついていないため、次は点クラスに方向の情報を持たせるように実装します。

