ネットワークのグラフ描画
日本語対応版も用意してみた。
事物や概念のネットワーク関係をグラフ表示すると分かり易い。関係に方向性がある場合を有効グラフで、方向性がない場合を無向グラフで描画する。有向グラフをジャンケンのグー、チョキ、パーの勝ち負けを例として取り上げ、無向グラフを関東の1都6県1湾の離接関係を例とした。サンプルファイルはsamplefiles.zipに、まとめた。
次の例の後で、双方向エッジの描画例も試みている。
ジャンケンの場合、グーはチョキに勝ち、チョキはパーに勝ち、パーはグーに勝つという相対的な関係がある。いま、勝ち負けを有向エッジで表す。例えば、グーがチョキに勝つことを、グーからチョキへの矢印で表すことにする。このグー・チョキ・パーの関係を有向グラフで表すスクリプトをリストA.1のように作成した。
リストA.1 グー・チョキ。パーの関係を表す有向グラフの描画スクリプト(rock_paper_scissors.py)
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_edge('Rock', 'Sciss') # グー > チョキ のエッジ
G.add_edge('Sciss', 'Paper') #
チョキ > パー のエッジ
G.add_edge('Paper', 'Rock') # パー > グー のエッジ
pos = nx.spring_layout(G)
# グラフの位置データ
nx.draw(G, pos, with_labels = True,
node_size=3000,
arrowstyle='-|>', arrowsize=50)
# グラフの描画
plt.show()
# グラフの表示
次のコードにより、有向グラフ描画の準備をしている。
G = nx.DiGraph()
次の3つのコードで、3本の有向エッジを加えている。
G.add_edge('Rock', 'Sciss') # グー > チョキ のエッジ
G.add_edge('Sciss', 'Paper') #
チョキ > パー のエッジ
G.add_edge('Paper', 'Rock') # パー > グー のエッジ
エッジを加えたのち、次のコードでグラフの配置を読み込んで、描画を実行している。
pos = nx.spring_layout(G)
# グラフの位置データ
nx.draw(G, pos, with_labels = True,
node_size=3000,
arrowstyle='-|>', arrowsize=50)
# グラフの描画
描画したグラフは、次のコマンドで表示される。
plt.show()
リストA.1のスクリプトを実行すると、図A.1のグラフが表示される。

図A.1
3変数、X、Y、Z、において、ZからXおよびYへの回帰係数を表すエッジを普通の矢印で、XとYの相関関係を表すエッジを双方向の矢印で表してみた(図A.2)。

図A.2
図A.2は次のスクリプトで描いた。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_edge('Z', 'X') # エッジ Z -> X
G.add_edge('Z', 'Y') # エッジ Z
-> Y
G.add_edge('X', 'Y') # エッジ X -> Y
G.add_edge('Y', 'X') # エッジ Y -> X
pos = nx.spring_layout(G)
# グラフの位置データ
nx.draw(G, pos, with_labels = True,
font_size=30, # グラフの描画
node_size=3000, node_color='orange',
arrowstyle='-|>', arrowsize=50)
nx.draw_networkx_edge_labels(G, pos,
edge_labels={('Z','X'):r'$\alpha$=0.7', # Z -> X のラベル
('Z','Y'):r'$\alpha$=0.6', #
Z -> Y のラベル
('X','Y'):r'$r^{2}$=0.5'}, #
X -> Y のラベル
font_size=20)
plt.show() # グラフの表示
次のコード
G.add_edge('X', 'Y') # エッジ X -> Y
G.add_edge('Y', 'X') # エッジ Y -> X
により、双方向の矢印を設定している。
次のコードにより、矢印にラベルとして数値的意味を表す文字列を付けている。
edge_labels={('Z','X'):r'$\alpha$=0.7', # Z -> X のラベル
('Z','Y'):r'$\alpha$=0.6', #
Z -> Y のラベル
('X','Y'):r'$r^{2}$=0.5'}, #
X -> Y のラベル
無向グラフの例として、関東の1都6県1湾の離接関係を無向グラフで表してみる。隣接関係を、図B.1に示すExcelファイルとして用意した。

図B.1
Kana神奈川県)、Tokyo(東京都)、Sai(埼玉県)、Gun(群馬県)、Toch(栃木県)、Iba(茨城県)、Chib(千葉県、Tbay(東京湾)の隣接関係を表し、隣接している場合は1,隣接していない場合は0が設定されている。
この図B.1のデータを読み込んで、無向グラフを描くスクリプトをリストB.1のように用意した。
リストB.1 無向グラフのスクリプト(Kanto.py)
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_excel('Kanto.xlsx') # Excelファイルの読み込み
nodes = df.values[:,0]
# ノード名のリスト
data = df.values[:,1:]
# ノード間の隣接データ
n = len(data)
# ノード数
G = nx.Graph()
for i in range(n-1):
for j in range(i+1, n):
if
data[i][j] == 1:
G.add_edge(nodes[i], nodes[j]) # エッジの追加
pos = nx.spring_layout(G)
# 配置の位置
nx.draw(G, pos, node_size=2000,
with_labels = True, node_color='aqua')
# 描画
plt.show()
# 表示
次のスクリプトで、Excelファイルを読み込んで、必要なデータを得ている。
df = pd.read_excel('Kanto.xlsx') # Excelファイルの読み込み
nodes = df.values[:,0]
# ノード名のリスト
data = df.values[:,1:]
# ノード間の隣接データ
n = len(data)
# ノード数
次のコードで無向グラフ描画の準備を行っている。
G = nx.Graph()
隣接を表すエッジの追加は、以下のスクリプトで行っている。
for i in range(n-1):
for j in range(i+1, n):
if
data[i][j] == 1:
G.add_edge(nodes[i], nodes[j]) # エッジの追加
エッジの追加後、配置を決め、グラフの描画が次のスクリプトで行われている。
pos = nx.spring_layout(G)
# 配置の位置
nx.draw(G, pos, node_size=2000,
with_labels = True, node_color='aqua')
# 描画
次のコードで、グラフが表示される。
plt.show()
リストB.1のスクリプトを実行すると、図B.2のようなグラフが表示される。

図B.2
グラフにおける布置は、実行により変わる可能性がある。このことを見るために、リストB.2を用意した。
リストB.2 複数のグラフを描くスクリプト(Knto_multi.py)
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_excel('Kanto.xlsx') # Excelファイルの読み込み
nodes = df.values[:,0]
# ノード名のリスト
data = df.values[:,1:]
# ノード間の隣接データ
n = len(data)
# ノード数
for i in range(9):
plt.subplot(3,3,i+1)
# 表示画面を3×3に分割
G = nx.Graph()
for i in range(n-1):
for
j in range(i+1, n):
if data[i][j] == 1:
G.add_edge(nodes[i], nodes[j]) # エッジの追加
pos =
nx.spring_layout(G)
# 配置の位置
nx.draw(G, pos,
node_size=100, with_labels = True, node_color='aqua') # 描画
plt.tight_layout()
plt.show()
リストB.2のスクリプトを実行すると、図B.3のようなグラフが表示される。

図B.3
9枚のグラフが描かれている。隣接関係の2次元上の表示には、自由度があるので、適切なものを選ぶ必要がある。
上記のサンプルプログラムの日本語対応版を用意してみた。使用日本語フォントは、パソコンに用意されているものから選ぶ。使用可能なフォントを調べるプログラムをこのウェブサイトに用意している。以下の例では、Microsoft JhengHeiを使用した。
グウ・チョキ・パーの関係を表示するスクリプトを、リストC.1のように用意した。
リストC.1 ジャンケンの関係の日本語表示
import networkx as nx
import matplotlib.pyplot as plt
cnvs = plt.figure()
G = nx.DiGraph()
G.add_edge('グー', 'チョキ') # グー > チョキ のエッジ
G.add_edge('チョキ', 'パー') # チョキ > パー のエッジ
G.add_edge('パー', 'グー') # パー > グー のエッジ
pos = nx.spring_layout(G)
# グラフの位置データ
nx.draw(G, pos, font_size=18,
with_labels = True, node_size=3000, node_color='orange',
edgecolors='k',
arrowstyle='-|>', arrowsize=100,font_family='Microsoft JhengHei'
)
# グラフの描画
plt.show()
# グラフの表示
リスト3を実行すると、図C.1のようなグラフが表示される。

図C.1
地域の隣接関係を表すグラフの描画スクリプト例を、リストD.1のように用意した。地域は、図B.1のデータに、いずれとも隣接しない地域としてハワイを加えた(図D.1)。

図D.1
図D.1のデータを読み込んでネットワーク描画を行うスクリプトをリストD.1のように用意した。
リストD.1 地域の隣接関係を表すグラフ描画
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
df =
pd.read_excel('Kanto_jp.xlsx')
# Excelファイルの読み込み
nodes = df.values[:,0]
# ノード名のリスト
data = df.values[:,1:]
# ノード間の隣接データ
n = len(data)
# ノード数
G = nx.Graph()
# 無向グラフの準備
G.add_nodes_from(nodes)
# ノードをすべて追加
for i in range(n-1):
for j in range(i+1, n):
if
data[i][j] == 1:
G.add_edge(nodes[i], nodes[j]) # エッジの追加
pos = nx.spring_layout(G)
# 配置の位置
nx.draw(G, pos, node_size=2000,
with_labels = True, node_color='aqua',
font_family='Microsoft JhengHei'
) # 描画
plt.show()
# 表示
上のスクリプトでは、隣接関係のないハワイを描画するために、次のコードでノードをすべて加えている。
G.add_nodes_from(nodes) # ノードをすべて追加
リストD.1のスクリプトを実行すると、図D.2のようなグラフが表示される。

図D.2
隣接関係のないハワイがエッジもなく離れて描画されている。