今回はpython
の強力なネットワーク分析ツールNetworkX
を紹介します。
NetworkX
を使用すると
- ネットワーク分析
- ネットワーク構造の可視化
- 中心性や連結性などの解析
を行うことができます。
この記事は次のドキュメントや本を参考にしています。
- 公式ドキュメント|Overview of NetworkX — NetworkX 2.4 documentation
- Pythonで学ぶネットワーク分析: ColaboratoryとNetworkXを使った実践入門
興味が湧いた方はぜひこちらもチェックしてみてください!
- ネットワーク分析の準備
- ネットワーク分析・可視化の超基本形
- 基本的な特性値の出力
- ネットワーク図の見た目変更
- ネットワーク可視化例|次数に応じた配色・サイズ変更
- ネットワーク分析おススメの1冊!
- おわりに
ネットワーク分析の準備
基本用語の整理
まずは、ネットワーク分析に関する超基本用語を整理していきましょう。
次の4つの用語をおさえれば、簡単な可視化は可能です。
- ネットワーク=グラフ,
Graph
- 頂点=ノード,
node
- 辺=エッジ,
edge
- 頂点の持つ辺の数=次数,
degree
NetworkX
のオブジェクトは英語名をもとに命名されているので、英語名を覚えた方が良いです。
環境構築
NetworkX
は組み込みライブラリではないので、pip
またはconda
でインストールします。
ターミナルで次のコマンドを打ってインストールします。
pip install network
conda install network
環境構築は飛ばして、とりあえずネットワーク分析を試したい場合は、Google Colaboratoryを使用すれば、初めからインストールされているので設定不要です。
networkxのインポート
NetworkX
はnx
という別名でインポートする慣例があるようです。
import networkx as nx
ネットワーク分析ではグラフの出力をすることもあるので、一緒にmaplotlib
もインストールしておくと楽ですね。
%matplotlib inline
# ↑jupter notebookで使用する場合のマジックコマンド
import matplotlib.pyplot as plt
import networkx as nx
ネットワーク分析・可視化の超基本形
ネットワークの可視化のためには、次の手順を踏みます。
Graph
オブジェクトの作成:G = nx.Graph()
node
の追加:G.add_nodes_from([node1, node2, node3,…])
edge
の追加:G.add_edges_from([(node1, node2), (node2, node3), …])
- ネットワークの可視化:
nx.draw(G, witlabels = True)
オブジェクト作成から、可視化までの基本形は次のようになります。
# Graphオブジェクトの作成
G = nx.Graph()
# nodeデータの追加
G.add_nodes_from(["A", "B", "C", "D", "E", "F"])
# edgeデータの追加
G.add_edges_from([("A", "B"), ("B", "C"), ("B", "F"),("C", "D"), ("C", "E"), ("C", "F"), ("B", "F")])
# ネットワークの可視化
nx.draw(G, with_labels = True)
plt.show()
これで、次のようなグラフが描けます。
以下では、このネットワークをもとに、
- ノード、エッジ、次数の出力方法
- ネットワーク図の装飾方法
- ネットワークの超簡単な分析例
を紹介していきます。
基本的な特性値の出力
nx.info()
関数で、Graph
オブジェクトの情報をテキストで出力できます。
print(nx.info(G))
# Name:
# Type: Graph
# Number of nodes: 6
# Number of edges: 6
# Average degree: 2.0000
Graph
オブジェクトの情報をさっと確認したい場合には便利です。
細かい情報が欲しい場合には、以下で紹介するようなメソッドを使用します。
ノードの出力
ノードの基本出力メソッド:
- ノードの総数:
G.number_of_nodes()
- ノードの要素:
G.nodes()
出力例を見ていきます。
print("number of nodes:",G.number_of_nodes())
print("nodes:", G.nodes())
number of nodes: 6
nodes: ['A', 'B', 'C', 'D', 'E', 'F']
エッジの出力
エッジの基本出力メソッド:
- エッジの総数:
G.number_of_edges()
- エッジの要素:
G.edges()
出力例を見ていきます。
print("number of edges:",G.number_of_edges())
print("edges:", G.edges())
number of edges: 6
edges: [('A', 'B'), ('B', 'C'), ('B', 'F'), ('C', 'D'), ('C', 'E'), ('C', 'F')]
次数の出力
次数の基本出力メソッド:
- 各ノードの次数:
G.degrees()
出力例を見ていきます。
print("degrees:", G.degrees())
degrees: [('A', 1), ('B', 3), ('C', 4), ('D', 1), ('E', 1), ('F', 2)]
各ノードの次数が自動集計・出力されます。
ネットワーク図の見た目変更
nx.draw()
メソッドにキーワード引数を設定することで、ネットワーク図の見た目を変更することができます。
ここでは、次の基本的なキーワード引数を紹介します。
- ノード関連:
- 色:
node_color
(デフォルト:'C0'
薄い青) - サイズ:
node_size
(デフォルト:300
)
- 色:
- エッジ関連:
- 色:
edge_color
(デフォルト:'black'
黒) - 太さ:
width
(デフォルト:1
)
- 色:
一括で設定(色、ノードサイズ、エッジの太さ)
キーワード引数としてシリアル値(リストでなく1つの値)を与えると、グラフ全体に適用されます。
ノードの色を"red"
、エッジの色を"gray"
、太さを500
にしてみましょう。
nx.draw(G, with_labels=True, node_color = "red", edge_color = "gray", node_size = 500, width = 5)
plt.show()
ネットワーク図の見た目が一括で変更されていますね。
各要素で異なる設定を適用
リストで設定値を渡すことで、各ノード、エッジに異なる設定を適用できます。
各要素の順番に対応するように設定値を渡します。
次の例ではノードの各要素の色をcolors
というリストで渡しています。
colors = ["lightblue", "green", "red", "cyan", "magenta", "yellow"]
nx.draw(G, with_labels=True, node_color = colors)
同様に、node_size
やedge_color
、width
などもリストで設定することが可能です。
ネットワークの特徴に合わせて見た目を設定すると見やすい図を作成できます。
このようなネットワークの可視化については、次の本で詳しく解説されています。
この本や公式ドキュメントで、基本的な分析、可視化方法を学んでいくのがおススメです!
ネットワーク可視化例|次数に応じた配色・サイズ変更
最後に、各ノードの次数に応じて配色・サイズ変更する例を紹介します。
これまで、紹介してきた特性値の出力方法、ネットワーク図の見た目変更を組み合わせていきます。
次の図のように、
- 各ノードの次数順の棒グラフ
- 次数に応じたネットワーク図
を作成してみましょう。
このグラフは
- 棒グラフとネットワークで各ノードの色が対応
- ネットワーク図のノードのサイズが次数の数に比例
するように作成しています。
デフォルトのネットワーク図よりも視認性がだいぶ上がっています。
きっと人に見せるときも、魅力的な図になりましたね!
次数に応じたネットワーク図の例
まずは、ノードの色付け、次数に応じたサイズ調整を行いましょう。
# ネットワーク全体の次数の平均値を計算
average_deg = sum(d for n, d in G.degree()) / G.number_of_nodes()
# ノードの次数に比例するようにサイズを設定
sizes = [300*deg/average_deg for node, deg in G.degree()]
print(sizes)
# [150.0, 450.0, 600.0, 150.0, 150.0, 300.0]
# グラフの出力
plt.figure(figsize = (10,5))
plt.subplot(121)
nx.draw(G, with_labels=True, node_color = colors, node_size = sizes, edge_color = "black")
plt.show() # ←棒グラフと並べて表示する場合は消します。
次数順の棒グラフの作成
次に各ノードの次数順の棒グラフを作成します。
# 次数の多い順番でnodeを並び替える
nodes_sorted_by_degree = sorted(G.degree(), key=lambda x: x[1], reverse=True)
print(nodes_sorted_by_degree)
# [('C', 4), ('B', 3), ('F', 2), ('A', 1), ('D', 1), ('E', 1)]
# 色のリストを次数順に並び替える
colors_dict = dict(zip(G.nodes(), colors))
colors_sorted = [colors_dict[node] for node, _ in nodes_sorted_by_degree]
print(colors_sorted)
# ['red', 'green', 'yellow', 'lightblue', 'cyan', 'magenta']
# グラフの出力
x, height = list(zip(*nodes_sorted_by_degree))
plt.subplot(122)
plt.xlabel("Number of degrees")
plt.ylabel("Name of node")
plt.barh(x, height, color = colors_sorted)
plt.show()
ネットワーク分析おススメの1冊!
pythonでネットワーク分析をしたい方には、こちらの本がおススメです。
実は私はネットワーク分析の基本どころか、NetworkX
の存在すらしらなかったのですが…。
この本では
- ネットワーク分析の流れや用語説明
NetworkX
をサンプルコード付きで解説
されています。
私のような初学者でもすぐに簡単なネットワーク分析をできるようになりました!
今回の記事では紹介しませんでしたが、本の中では
- ネットワークの中心性を解析する方法
- グループの分割・抽出方法
などに関しても解説されています。
ネットワーク分析の勉強にオススメな1冊でした!
おわりに
今回はネットワーク分析、NetworkX
に関して紹介しました。
ネットワークを可視化すると、一気にデータが意味を持ちだすような印象を持ちます。
pythonの可視化にはmatplotlib
を使用することが多いです。
今回も自然な流れでsubplot
を使用していました。
matplotlibの簡単な使い方については、こちらの記事もご覧ください!
Twitter@YutaKaでは、ほぼ毎日pythonに関する情報を発信しています。
気楽にツイートしているので、気軽にフォローしてください!