社会ネットワーク分析(SNA: Social Network Analysis)
【概要】
本記事は、社会ネットワーク分析(SNA)の基本概念と、Python の NetworkX ライブラリを用いた中心性分析の実装を解説する。題材として論文の引用ネットワークを取り上げ、有向・重み付きグラフに対する中心性指標の計算と、その結果の解釈までを示す。
社会ネットワーク分析(SNA)は、グラフ理論を基盤として個体間の関係を定量的に分析する手法である。SNA ではネットワークをノード(node)とエッジ(edge)で表現する。ノードは人物・組織・論文などのアクターを表し、エッジはノード間の関係を表す。エッジには重み(weight)を付与でき、関係の強さや頻度を表現できる。有向グラフを用いれば、引用関係や影響関係のような方向性のある関係を扱える。
各中心性指標はネットワーク内の異なる役割を測るため、指標が変われば最も値の高いノードも変わる。後出のサンプルでは、被引用の中心は E、仲介役は B となる。SNA で複数の指標を併用するのはこのためである。
本記事のコードは Windows 上で動作し、CPU のみで実行できる。導入はコマンドプロンプトまたは PowerShell で次のコマンドを実行する。NetworkX 3.0 以降の pagerank は SciPy を必要とするため、scipy も導入対象に含める。
pip install -U --no-user networkx matplotlib scipy
【目次】
1. 他の分析手法との比較
従来の統計手法の多くは、個体の属性(年齢、性別、収入など)に着目し、サンプルの独立性を仮定する。これに対して SNA は、個体間のつながりの有無とつながり方そのものを分析対象とし、ネットワーク構造を明示的にモデル化して定量化する。
2. 原理
2.1 基本構造:グラフ表現
ネットワークはグラフ G = (V, E) で表現する。V はノードの集合、E はエッジの集合である。
無向グラフはエッジに方向性がなく、友人関係のような双方向の関係を表す。有向グラフはエッジに方向性があり、引用関係や影響関係を表す。本記事では有向グラフを扱う。
エッジには重みを付与できる。重みは関係の強さや頻度を表し、例えば引用回数や影響の強さを重みとする。本記事では、重みを正の重要度として定義する。後出の指標のうち最短経路を用いるものでは、NetworkX の引数で指定する値は距離として扱われる。重みが大きいほど二者を近いと捉えるため、重みの逆数を距離として用いる。
2.2 主要な分析指標
以下の指標でネットワーク構造を評価する。指標によって重みの扱いが異なる。本記事のコードでは、媒介中心性と近接中心性は distance 属性(重みの逆数)を用いる。PageRank は weight 属性(引用の重要度)をそのまま用いる。密度と次数中心性は重みを考慮しない。
ネットワーク全体の指標
密度(Density)は、実際のエッジ数を最大エッジ数で割った値である。自己ループを含まない有向グラフでは A→B と B→A を別のエッジとして数える。最大エッジ数は N × (N-1)、密度は D = E / (N × (N-1)) である(N はノード数、E はエッジ数)。密度は重みを考慮しない。
ノードレベルの指標(中心性指標)
次数中心性(Degree Centrality)は、ノードに接続するエッジの数を基にした指標である。有向グラフでは入次数と出次数を区別する。値は接続ノード数を最大可能数(N-1)で割って正規化される(例:6 ノードのネットワークで 4 つのノードから引用されていれば 4 / 5 = 0.800)。次数中心性は重みを考慮しない。
入次数中心性(In-degree Centrality)は、そのノードに入るエッジの数を基にした指標である。被参照数やフォロワー数に相当し、受信者としての重要性を示す。
出次数中心性(Out-degree Centrality)は、そのノードから出るエッジの数を基にした指標である。参照数やフォロー数に相当し、発信者としての活発さを示す。
媒介中心性(Betweenness Centrality)は、他のノード間の最短経路上にそのノードが含まれる頻度である。仲介者としての重要性を示す。重み付きエッジの場合、重みの逆数を距離として計算する。本記事のコードでは NetworkX の既定どおり正規化された値を用いる。有向グラフでは、始点と終点を区別したノード対に基づき (N-1)(N-2) で割って正規化される。出ていくエッジを持たない終端ノードは、どの最短経路の通過点にもならないため値が 0 になる。
近接中心性(Closeness Centrality)は、他のノードからそのノードへの最短距離の合計が小さいほど大きくなる指標である。重み付きエッジの場合、重みの逆数を距離として計算する。NetworkX の closeness_centrality は、到達可能なノードだけで距離を計算し、既定値 wf_improved=True により、ネットワーク全体に対する到達可能割合を掛ける。到達可能ノード数を r(自分自身を含む)、全ノード数を N、距離合計を S とすると、S が正のとき C = ((r - 1) / S) × ((r - 1) / (N - 1)) で計算される。重みの逆数を距離に使うと距離が 1 未満になることがあり、その場合は近接中心性が 1 を超えることがある。
近接中心性には方向の違いがある。NetworkX の closeness_centrality は、有向グラフに対して既定で入方向(inward)、すなわち他のノードから対象ノードへ到達する距離を計算する。出方向で評価する場合は G.reverse() を適用する。本記事では既定の入方向で計算する。引用ネットワークでは A→B が「A が B を引用する」を意味するため、入方向の近接中心性が高いノードは、多くの論文から短い距離で引用される被引用の中心と解釈できる。入ってくるエッジが一つもないノードは、他のノードから到達されないため値は 0 になる。
PageRank は、重要なノードからリンクされているノードほど値が高くなる指標である。入次数だけでなくリンク元の重要性も考慮する。重み付きエッジの場合、重みに応じてスコア配分が変わる。本記事のコードでは減衰係数 alpha=0.85 を用いる。出ていくエッジを持たないノードは、NetworkX の既定の扱いにより、全ノードへ均等にスコアを配分するものとして計算される。
2.3 重みがない場合
エッジに重みを設定しない場合、すべてのエッジの重みを 1 として扱う。この場合、媒介中心性と近接中心性はホップ数(経由するエッジの本数)で経路長を計算し、PageRank はすべてのエッジを同等に扱う。次章の演習では、正の重みを持つサンプルを用いて各指標を計算する。
3. 演習1.引用ネットワークの中心性分析
テーマ
論文の引用ネットワークを有向・重み付きグラフとして構築し、各中心性指標を計算して、指標ごとに値の高いノードがどう変わるかを確認する。論文 A が論文 B を引用する場合、A→B のエッジを作成する。重みは引用の重要度を表し、値が大きいほど重要な引用である。
サンプルネットワーク(引用関係):
A → B → D
↓ ↘ ↓
C → E ← F
エッジと重み:
A → B (重み: 3)
A → C (重み: 1)
A → E (重み: 2)
B → D (重み: 2)
B → E (重み: 1)
C → E (重み: 3)
F → E (重み: 2)
手順
コマンドプロンプトまたは PowerShell で pip install -U --no-user networkx matplotlib scipy を実行し、ライブラリを導入する。次のコードを実行(メモ帳を用いる場合は a.py のようなファイル名で保存して実行)する。実行すると、各中心性指標について全ノードの値と最も値の高いノードが表示され、続いてネットワーク図が表示される。
import networkx as nx
import matplotlib.pyplot as plt
# 有向グラフの構築
G = nx.DiGraph()
# エッジの第3要素は引用の重要度を表す重みである
edges = [
('A', 'B', 3), ('A', 'C', 1), ('A', 'E', 2),
('B', 'D', 2), ('B', 'E', 1),
('C', 'E', 3),
('F', 'E', 2)
]
# weight は引用の重要度、distance は最短経路計算用の距離である。
# 重要度が大きいほど近い関係とするため、distance = 1 / weight とする。
for source, target, importance in edges:
G.add_edge(source, target, weight=importance, distance=1 / importance)
# 表示順を固定する
nodes = sorted(G.nodes(), key=str)
# 入次数中心性と出次数中心性(重みは考慮されない)
in_degree_cent = nx.in_degree_centrality(G)
out_degree_cent = nx.out_degree_centrality(G)
# 媒介中心性
# NetworkX の betweenness_centrality の引数 weight には、
# 距離として使うエッジ属性名を指定する。
betweenness_cent = nx.betweenness_centrality(G, weight='distance')
# 近接中心性
# 有向グラフでは既定で入方向の距離を計算する。
# distance には、距離として使うエッジ属性名を指定する。
closeness_cent = nx.closeness_centrality(G, distance='distance')
# PageRank(重みを考慮)
# weight には、引用の重要度として使うエッジ属性名を指定する。
pagerank = nx.pagerank(G, alpha=0.85, weight='weight', max_iter=1000)
# 結果の表示(各指標について全ノードの値と、最も値の高いノードを表示)
metrics = {
"入次数中心性": in_degree_cent,
"出次数中心性": out_degree_cent,
"媒介中心性(重み付き)": betweenness_cent,
"近接中心性(重み付き・入方向)": closeness_cent,
"PageRank(重み付き)": pagerank,
}
for name, cent in metrics.items():
top = max(nodes, key=lambda node: cent[node])
print(f"\n=== {name} ===")
for node in nodes:
print(f" {node}: {cent[node]:.3f}")
print(f" 最も値の高いノード: {top}({cent[top]:.3f})")
# ネットワーク全体の指標
print("\n=== ネットワーク全体の指標 ===")
print(f" ノード数: {G.number_of_nodes()}")
print(f" エッジ数: {G.number_of_edges()}")
print(f" 密度: {nx.density(G):.3f}")
# ネットワークの可視化
pos = nx.spring_layout(G, seed=42, weight='weight')
edge_labels = nx.get_edge_attributes(G, 'weight')
plt.figure(figsize=(6, 4))
nx.draw(
G,
pos,
with_labels=True,
node_color='lightgreen',
node_size=700,
font_size=14,
arrows=True
)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
plt.axis('off')
plt.show()
実行結果は次のとおりである。
=== 入次数中心性 ===
A: 0.000
B: 0.200
C: 0.200
D: 0.200
E: 0.800
F: 0.000
最も値の高いノード: E(0.800)
=== 出次数中心性 ===
A: 0.600
B: 0.400
C: 0.200
D: 0.000
E: 0.000
F: 0.200
最も値の高いノード: A(0.600)
=== 媒介中心性(重み付き) ===
A: 0.000
B: 0.050
C: 0.000
D: 0.000
E: 0.000
F: 0.000
最も値の高いノード: B(0.050)
=== 近接中心性(重み付き・入方向) ===
A: 0.000
B: 0.600
C: 0.200
D: 0.600
E: 1.371
F: 0.000
最も値の高いノード: E(1.371)
=== PageRank(重み付き) ===
A: 0.101
B: 0.144
C: 0.116
D: 0.183
E: 0.355
F: 0.101
最も値の高いノード: E(0.355)
=== ネットワーク全体の指標 ===
ノード数: 6
エッジ数: 7
密度: 0.233
ヒント
入次数中心性は接続ノード数を N-1(ここでは 5)で割った値である(例:E は 4 / 5 = 0.800)。出次数中心性も同様に、外向きの接続ノード数を N-1 で割った値である(例:A は 3 / 5 = 0.600)。
媒介中心性は、最短経路の通過点になった割合を表す。本サンプルで通過点が生じるのは、A から D への最短経路 A→B→D の B のみである。A から E へは直接エッジの距離が 1 / 2 = 0.5 であり、A→B→E(1 / 3 + 1 ≈ 1.333)や A→C→E(1 + 1 / 3 ≈ 1.333)より短いため、B や C は通過点にならない。有向グラフの正規化では N=6 のとき (N-1)(N-2)=20 で割るため、B の値は 1 / 20 = 0.050 になる。
近接中心性が 1 を超えるのは、重みの逆数を距離に使うためである。E については、A から E への距離が 0.5、B から E への距離が 1、C から E への距離が約 0.333、F から E への距離が 0.5 であり、距離合計は約 2.333 である。到達可能ノード数は自分自身を含めて 5、全ノード数は 6 であるため、(4 / 2.333) × (4 / 5) ≈ 1.371 になる。A と F は入ってくるエッジを持たないため 0 である。
考察ポイント
入次数中心性と出次数中心性を比較し、E は受信側(被引用)で最大、A は発信側(引用)で最大であることを読み取る。媒介中心性では B のみが値を持つ。一方、E は引用を多く受けるが出ていくエッジを持たない終端ノードのため、媒介中心性は 0 となる。近接中心性(入方向)と PageRank では E が最大であり、被引用の中心であることが確認できる。指標によって値の高いノードが E と B に分かれる点に着目し、各指標がネットワーク内のどの役割を測っているかを読み取る。
4. まとめ
SNA は個体間の関係を分析する手法である。中心性指標を用いて、ネットワーク内のアクターの位置づけや全体構造を評価する。方向性のある関係には有向グラフを用い、入次数中心性・出次数中心性・PageRank で発信と受信の重要性を分析する。エッジに重みを設定すれば、関係の強さを考慮した分析ができる。ただし、最短経路を用いる媒介中心性と近接中心性では、重要度としての重みをそのまま距離にせず、重みの逆数を距離として用いる。各指標が測る役割は異なるため、複数の指標を併用してアクターを多面的に評価する。