NetworkXでワートリの人間関係をネットワーク可視化・分析する【Python】

Pythonのネットワークライブラリ「NetworkX」を使って、ワールドトリガーのキャラクターの人間関係をネットワーク可視化・分析してみます。

NetworkXのdocumentationはこちら。


ライブラリのインポート

最初に使用するライブラリをインポート。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import japanize_matplotlib
import networkx as nx
import numpy as np

ネットワークの元データの読み込み

ネットワークのデータは、Excel→Pandas→NetworkXの順番でNetworkXに渡します。

まず最初に、Excelで元データを作成します。
キャラの関係性は、ワートリ公式ファンブック「BBF」に載っている各キャラの「ミニ相関図(Relation)」を使いました。ひたすらExcelに入力。

Excelを読み込んでPandasのDataframeにします。

df = pd.read_excel("/content/BBF.xlsx", sheet_name="関係性")

ネットワーク作成

DataFrameからNeworkxのネットワークを作成します。
source(始点)とtarget(終点)の列を指定します。

G = nx.from_pandas_edgelist(df, source="始点", target="終点")

とりあえず、可視化してみます。
posはネットワークの配置を決定するパラメータです。kamada_kawai_layout以外にもspring_layoutとか色々とあります。

pos = nx.kamada_kawai_layout(G)

plt.figure(figsize=(10,10))

nx.draw_networkx_nodes(G, pos, node_color="skyblue", edgecolors="white", node_size=100)
nx.draw_networkx_labels(G, pos, font_family='IPAexGothic', font_size=10)
nx.draw_networkx_edges(G, pos, edge_color="grey", width=1)

plt.show()

キャラの関係をネットワーク可視化することができました。
パッと見た感じだと、中心に密集した集団があることや、関係性の少ないキャラがネットワークの端の方にいることが読み取れます。

ネットワーク分析:媒介中心性

ネットワークを分析してみましょう。
どのキャラクターが人間関係のハブになっているのか、媒介中心性を求めてみます。

betweenness_centrality = nx.betweenness_centrality(G)

top5_nodes = sorted(betweenness_centrality.items(), key=lambda x: x[1], reverse=True)[:5]

for node, centrality in top5_nodes:
    print(f"{node} : {round(centrality,2)}")

媒介中心性のTOP5は以下の通りでした。

三雲修 : 0.21
太刀川慶 : 0.14
雨取千佳 : 0.13
空閑遊真 : 0.13
奈良坂透 : 0.12

主人公の3人が上位でした。物語の中心のキャラクターが人間関係の中心になるのは納得です。
2位の太刀川さんは、上層部の忍田さんや玉狛の迅さんやB級の麻雀仲間など、部隊や派閥に関係なく顔が広いことが効いてそうです。ボーダーの個人1位が人間関係のハブを担ってるのは面白い発見でした。
4位の奈良坂先輩は、那須隊を中心ネットワークに繋ぐ位置にいることが効いてそうです。

どの関係性が重要かエッジの媒介中心性も求めてみます。

edge_betweenness = nx.edge_betweenness_centrality(G)
top5_edges = sorted(edge_betweenness.items(), key=lambda x: x[1], reverse=True)[:5]
for edge, centrality in top5_edges:
    print(f"{edge} : {round(centrality,2)}")

('冬島慎次', '諏訪洸太郎') : 0.09
('当間勇', '奈良坂透') : 0.08
('太刀川慶', '村上鋼') : 0.07
('奈良坂透', '古寺章平') : 0.07
('空閑遊真', '影浦雅人') : 0.07

当然と言えば当然ですが、部隊の違う隊員を繋ぐエッジの重要度が高い結果になりました。

ノードとエッジの媒介中心性を反映して、ネットワークをもう一度可視化してみましょう。

edge_thickness = [1 + 20 * centrality for centrality in edge_betweenness.values()]

node_size = [10 + betweenness_centrality[node] * 1000 for node in G.nodes()]

plt.figure(figsize=(10,10))

nx.draw_networkx_nodes(G, pos, node_color="skyblue", edgecolors="white", node_size=node_size)
nx.draw_networkx_labels(G, pos, font_family='IPAexGothic', font_size=10)
nx.draw_networkx_edges(G, pos, edge_color="grey", width=edge_thickness)

plt.show()

ネットワーク分析:コミュニティ抽出

ネットワークをいくつかのグループに分けて解釈しやすくしたいと思います。
Louvain法を用いたコミュニティ抽出を行います。

communities = list(nx.community.louvain_communities(G))

抽出したコミュニティをもとに、ノードとエッジの色を変更します。
ノードは、コミュニティに対応した色。
エッジは、コミュニティ内であればコミュニティに対応した色、コミュニティ間であれば2つのコミュニティの中間の色とします。

color_map = plt.cm.get_cmap('Set2', len(communities))

node_communities = {}

for idx, community_nodes in enumerate(communities):
    for node in community_nodes:
        node_communities[node] = idx

node_colors = [color_map(node_communities[node]) for node in G.nodes]

edge_colors = []
for u, v in G.edges():
    color_u = color_map(node_communities[u])
    color_v = color_map(node_communities[v])
    intermediate_color = tuple(np.mean([color_u, color_v], axis=0).astype(float))
    edge_colors.append(intermediate_color)

plt.figure(figsize=(10,10))
nx.draw_networkx_nodes(G, pos, node_color=node_colors, node_size=node_size, edgecolors="white")
nx.draw_networkx_labels(G, pos, font_family='IPAexGothic', font_size=10)
nx.draw_networkx_edges(G, pos, width=edge_thickness, edge_color=edge_colors)
plt.show()

茶色のコミュニティは風間隊、青色のコミュニティは那須隊など、ある程度は部隊の関係性も反映しつつ部隊を横断したコミュニティが形成されました。
視覚的にも見やすくなってるのではないかと思います。

おわりに

NetworkXを用いたネットワーク可視化・分析をやってみました。

今回はBBFの関係性だけを使いましたが、BBF発売当時には登場していなかったキャラクターや関係性を追加してみると、また違うボーダーの人間関係が見えてくるかもしれませんね。BBF2の発売が待ち遠しいです。

この記事が気に入ったらサポートをしてみませんか?