STEP 27: ネットワーク図の作成

🕸️ STEP 27: ネットワーク図の作成

つながりのあるデータをネットワーク図で可視化しよう!

📋 このステップで学ぶこと

  • ネットワーク図(グラフ理論)の基礎概念
  • NetworkXライブラリの基本的な使い方
  • ノードとエッジの作成・操作
  • レイアウトアルゴリズムの種類と選び方
  • 有向グラフと重み付きグラフ
  • 実務での活用例(SNS分析、組織図、推薦システム)

🌐 1. ネットワーク図とグラフ理論

ネットワーク図とは何か

ネットワーク図(Network Graph)は、つながり(関係性)を持つデータを可視化する手法です。数学ではグラフ理論(Graph Theory)と呼ばれる分野に属します。

ここで言う「グラフ」は棒グラフや折れ線グラフとは別物です。「点(ノード)」と「線(エッジ)」で構成される図形のことを指します。

💡 身近なネットワークの例

私たちの周りには様々なネットワークがあります:

SNS:ユーザー(ノード)とフォロー関係(エッジ)
交通網:駅(ノード)と路線(エッジ)
組織図:社員(ノード)と報告関係(エッジ)
Webサイト:ページ(ノード)とリンク(エッジ)
友人関係:人(ノード)と友達関係(エッジ)

【ネットワーク図の構成要素】 ■ ノード(Node)/ 頂点(Vertex) ├── 個々の要素を表す「点」 ├── 人、組織、商品、駅など └── 円や点で描画される ■ エッジ(Edge)/ 辺(Link) ├── ノード間のつながりを表す「線」 ├── フォロー関係、友達関係、路線など └── 直線や曲線で描画される 【図解】 (A)───(B) │ ╲ │ │ ╲ │ (C)───(D) ノード: A, B, C, D エッジ: A-B, A-C, A-D, B-D, C-D
🕸️ ネットワーク図の活用場面
分野 ノード エッジ 分析の目的
SNS分析 ユーザー フォロー関係 インフルエンサー発見
組織分析 社員・部署 コミュニケーション 情報伝達の改善
推薦システム 商品 同時購入 関連商品の発見
交通最適化 駅・交差点 路線・道路 最短経路の計算
知識グラフ 概念・エンティティ 関係性 知識の構造化
💡 ネットワークの3つの種類
種類 特徴
無向グラフ エッジに方向性がない(双方向) 友達関係、共著関係
有向グラフ エッジに方向性がある(一方向) フォロー関係、リンク
重み付きグラフ エッジに強さや距離がある 距離、通信量、親密度

📦 2. NetworkXの基本

NetworkXとは

NetworkXは、Pythonでネットワーク(グラフ)を作成・操作・分析するためのライブラリです。ノードとエッジの追加、レイアウト計算、中心性分析など、ネットワーク分析に必要な機能が揃っています。

📝 ステップ1: ライブラリのインストールと読み込み

まずはNetworkXをインストールして読み込みます。

# Google Colabではインストール済みですが、念のため !pip install networkx import networkx as nx import matplotlib.pyplot as plt
【コードの意味】 !pip install networkx ├── pip: Pythonのパッケージ管理ツール ├── install networkx: NetworkXをインストール └── Google Colabでは通常インストール済み import networkx as nx ├── networkx: ネットワーク分析ライブラリ └── nx という短い名前で使えるようにする import matplotlib.pyplot as plt ├── グラフの描画に使用 └── NetworkXの描画機能はMatplotlibに依存
📝 ステップ2: 空のグラフを作成

まず空のグラフ(ネットワーク)を作成し、そこにノードとエッジを追加していきます。

# 空のグラフ(無向グラフ)を作成 G = nx.Graph()
【グラフオブジェクトの種類】 nx.Graph() ├── 無向グラフを作成 └── エッジに方向性がない(A-B = B-A) nx.DiGraph() ├── 有向グラフ(Directed Graph)を作成 └── エッジに方向性がある(A→B ≠ B→A) nx.MultiGraph() ├── 多重辺グラフを作成 └── 同じノード間に複数のエッジを持てる 【変数名について】 ・Gはグラフ(Graph)の頭文字 ・慣習的にグラフはGと書くことが多い
📝 ステップ3: ノードを追加

グラフにノード(点)を追加します。

# ノードを1つずつ追加 G.add_node(‘A’) G.add_node(‘B’) G.add_node(‘C’) # 複数のノードをまとめて追加 G.add_nodes_from([‘D’, ‘E’, ‘F’])
【ノード追加メソッド】 G.add_node(‘A’) ├── 1つのノードを追加 ├── ノード名は文字列、数値、タプルなど何でもOK └── 同じ名前のノードを追加しても1つしか存在しない G.add_nodes_from([‘D’, ‘E’, ‘F’]) ├── リストで複数のノードをまとめて追加 └── 効率的に大量のノードを追加できる 【ノード名の例】 ・文字列: ‘A’, ‘太郎’, ‘Tokyo’ ・数値: 1, 2, 3 ・タプル: (1, 2), (‘user’, 123)
📝 ステップ4: エッジを追加

グラフにエッジ(線)を追加します。エッジは2つのノードをつなぎます。

# エッジを1つずつ追加 G.add_edge(‘A’, ‘B’) # AとBをつなぐ G.add_edge(‘B’, ‘C’) # BとCをつなぐ G.add_edge(‘C’, ‘A’) # CとAをつなぐ # 複数のエッジをまとめて追加 G.add_edges_from([(‘D’, ‘E’), (‘E’, ‘F’), (‘F’, ‘D’)])
【エッジ追加メソッド】 G.add_edge(‘A’, ‘B’) ├── AとBの間にエッジを追加 ├── 存在しないノードを指定すると自動的にノードも追加される └── 無向グラフでは A-B と B-A は同じエッジ G.add_edges_from([(‘D’, ‘E’), (‘E’, ‘F’), (‘F’, ‘D’)]) ├── タプルのリストで複数のエッジをまとめて追加 ├── 各タプルは (ノード1, ノード2) の形式 └── 効率的に大量のエッジを追加できる 【ポイント】 ・エッジを追加すると自動的にノードも追加される ・すでに存在するエッジを追加しても重複しない
📝 ステップ5: グラフの情報を確認

作成したグラフの情報を確認します。

# ノード数を確認 print(f”ノード数: {G.number_of_nodes()}”) # エッジ数を確認 print(f”エッジ数: {G.number_of_edges()}”) # ノード一覧を確認 print(f”ノード一覧: {list(G.nodes())}”) # エッジ一覧を確認 print(f”エッジ一覧: {list(G.edges())}”)
ノード数: 6 エッジ数: 6 ノード一覧: [‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’] エッジ一覧: [(‘A’, ‘B’), (‘A’, ‘C’), (‘B’, ‘C’), (‘D’, ‘E’), (‘D’, ‘F’), (‘E’, ‘F’)]
【情報取得メソッド】 G.number_of_nodes() └── グラフ内のノード数を返す G.number_of_edges() └── グラフ内のエッジ数を返す G.nodes() ├── ノードのイテレータを返す └── list()で囲むとリストに変換 G.edges() ├── エッジのイテレータを返す └── 各エッジは (ノード1, ノード2) のタプル 【その他の便利なメソッド】 G.degree(‘A’) # ノードAの次数(接続数) G.neighbors(‘A’) # ノードAに隣接するノード G.has_node(‘A’) # ノードAが存在するか G.has_edge(‘A’,’B’) # エッジA-Bが存在するか

基本的なネットワーク図を描画

作成したグラフを可視化します。nx.draw()関数で簡単に描画できます。

import networkx as nx import matplotlib.pyplot as plt # グラフ作成 G = nx.Graph() G.add_edges_from([ (‘A’, ‘B’), (‘A’, ‘C’), (‘A’, ‘D’), (‘B’, ‘C’), (‘B’, ‘E’), (‘C’, ‘F’), (‘D’, ‘E’), (‘E’, ‘F’) ]) # 描画設定 plt.figure(figsize=(10, 8)) # ネットワーク図を描画 nx.draw( G, with_labels=True, # ノードにラベル表示 node_color=’lightblue’, # ノードの色 node_size=1500, # ノードのサイズ font_size=16, # フォントサイズ font_weight=’bold’, # フォントの太さ edge_color=’gray’, # エッジの色 width=2 # エッジの太さ ) plt.title(‘基本的なネットワーク図’, fontsize=18, fontweight=’bold’) plt.axis(‘off’) # 軸を非表示 plt.tight_layout() plt.show()
【nx.draw()のパラメータ詳細】 nx.draw(G, …) ├── G: 描画するグラフオブジェクト └── 以下はオプションパラメータ with_labels=True ├── ノードにラベル(名前)を表示する └── Falseにすると点だけ表示 node_color=’lightblue’ ├── ノードの塗りつぶし色 ├── 色名、カラーコード、リストで指定可能 └── リストを渡すと各ノードを異なる色にできる node_size=1500 ├── ノードの大きさ(ピクセル) ├── デフォルトは300程度 └── リストを渡すと各ノードを異なるサイズにできる font_size=16 └── ラベルのフォントサイズ edge_color=’gray’ └── エッジの色 width=2 └── エッジの太さ plt.axis(‘off’) └── X軸・Y軸を非表示にする(ネットワーク図では通常非表示)

🎨 3. レイアウトアルゴリズム

レイアウトとは

ネットワーク図のノードをどこに配置するかを決めるのがレイアウトアルゴリズムです。同じネットワークでもレイアウトによって見え方が大きく変わります。

NetworkXには複数のレイアウトアルゴリズムが用意されており、目的に応じて使い分けます。

🎨 主要なレイアウトアルゴリズム
レイアウト 関数 特徴 適した用途
Spring spring_layout() バネモデルで自然な配置 一般的なネットワーク
Circular circular_layout() ノードを円形に配置 対称性の強調
Random random_layout() ランダムに配置 初期確認用
Shell shell_layout() 同心円状に配置 グループ分けがある場合
Kamada-Kawai kamada_kawai_layout() 距離を考慮した配置 距離を重視する場合
# レイアウトの使い方 pos = nx.spring_layout(G) # ノードの位置を計算 # 計算した位置を使って描画 nx.draw(G, pos=pos, …)
【レイアウトの仕組み】 pos = nx.spring_layout(G) ├── レイアウト関数はノードの座標を計算 ├── 戻り値は辞書形式: {‘A’: (x, y), ‘B’: (x, y), …} └── この座標をnx.draw()のpos引数に渡す nx.draw(G, pos=pos, …) ├── pos: ノードの配置位置を指定 └── 同じposを使えば再現性のある描画ができる 【Spring Layoutの仕組み】 ・ノードを「質点」、エッジを「バネ」と見なす ・バネの力で引っ張り合い、反発力で離れる ・この物理シミュレーションで自然な配置になる

レイアウトの比較

※ コードが長い場合は横スクロールできます

import networkx as nx import matplotlib.pyplot as plt # サンプルグラフ(Zachary’s Karate Club – 有名なサンプルデータ) G = nx.karate_club_graph() # 複数のレイアウトを比較 layouts = { ‘Spring Layout’: nx.spring_layout(G, seed=42), # バネモデル ‘Circular Layout’: nx.circular_layout(G), # 円形配置 ‘Random Layout’: nx.random_layout(G, seed=42), # ランダム配置 ‘Shell Layout’: nx.shell_layout(G) # シェル配置 } # 2×2のサブプロット fig, axes = plt.subplots(2, 2, figsize=(14, 12)) axes = axes.flatten() for i, (name, pos) in enumerate(layouts.items()): ax = axes[i] nx.draw( G, pos, node_color=’lightcoral’, node_size=300, with_labels=False, edge_color=’gray’, width=0.5, ax=ax ) ax.set_title(name, fontsize=14, fontweight=’bold’) ax.axis(‘off’) plt.suptitle(‘レイアウトアルゴリズムの比較’, fontsize=18, fontweight=’bold’) plt.tight_layout() plt.show()
【コードの解説】 nx.karate_club_graph() ├── NetworkXに付属の有名なサンプルデータ ├── 空手クラブのメンバー間の友人関係 └── 34ノード、78エッジ seed=42 ├── 乱数のシード値を固定 └── 毎回同じレイアウトを再現できる ax=ax ├── 描画先のサブプロットを指定 └── 複数のグラフを並べて表示するときに使用
💡 レイアウトの調整パラメータ

Spring Layoutは調整パラメータで見やすさを改善できます。

pos = nx.spring_layout( G, k=2, # ノード間の最適距離(大きいほど離れる) iterations=50, # 計算の繰り返し回数(多いほど最適化) seed=42 # 乱数シード(再現性のため) )
【spring_layoutのパラメータ】 k=2 ├── ノード間の最適距離を調整 ├── デフォルトは 1/√n(nはノード数) ├── 大きくするとノードが離れる └── ノードが重なるときは大きくする iterations=50 ├── 物理シミュレーションの繰り返し回数 ├── デフォルトは50 ├── 多いほど最適化されるが時間がかかる └── レイアウトが安定しないときは増やす seed=42 ├── 乱数シードを固定 └── 同じレイアウトを再現したいときに使用

🎯 4. ネットワーク図のカスタマイズ

ノードのサイズと色を変える

ノードのサイズをデータに応じて変えると、情報量が増して読み取りやすくなります。例えば、「接続数が多いノードを大きく表示する」といった表現ができます。

import networkx as nx import matplotlib.pyplot as plt # ソーシャルネットワークの例 G = nx.Graph() # 友人関係を追加 connections = [ (‘太郎’, ‘花子’), (‘太郎’, ‘次郎’), (‘太郎’, ‘美咲’), (‘花子’, ‘次郎’), (‘花子’, ‘健太’), (‘次郎’, ‘美咲’), (‘次郎’, ‘健太’), (‘美咲’, ‘健太’), (‘美咲’, ‘愛’), (‘健太’, ‘愛’), (‘健太’, ‘大輔’), (‘愛’, ‘大輔’) ] G.add_edges_from(connections) # 各ノードの接続数(次数)を計算 degree_dict = dict(G.degree()) print(“各ノードの接続数:”, degree_dict) # ノードの色とサイズを次数に応じて変更 node_colors = [degree_dict[node] for node in G.nodes()] node_sizes = [degree_dict[node] * 500 for node in G.nodes()]
【コードの解説】 G.degree() ├── 各ノードの次数(接続しているエッジの数)を取得 ├── [(‘太郎’, 3), (‘花子’, 3), …] のような形式 └── dict()で辞書に変換: {‘太郎’: 3, ‘花子’: 3, …} node_colors = [degree_dict[node] for node in G.nodes()] ├── ノードごとの次数をリスト化 ├── この数値がカラーマップに渡される └── 数値が大きい → 色が濃い(赤に近い) node_sizes = [degree_dict[node] * 500 for node in G.nodes()] ├── 次数 × 500 でノードサイズを計算 ├── 接続数が多いほど大きく表示 └── 500は調整用の係数(適宜変更)
# 可視化 plt.figure(figsize=(12, 10)) pos = nx.spring_layout(G, k=2, iterations=50) # エッジを描画(薄めに) nx.draw_networkx_edges(G, pos, alpha=0.3, width=2, edge_color=’gray’) # ノードを描画(色とサイズを変更) nx.draw_networkx_nodes( G, pos, node_color=node_colors, node_size=node_sizes, cmap=’YlOrRd’, # 黄→オレンジ→赤のカラーマップ alpha=0.9 ) # ラベルを描画 nx.draw_networkx_labels(G, pos, font_size=12, font_weight=’bold’) plt.title(‘ソーシャルネットワーク\n(ノードサイズ・色 = 友達の数)’, fontsize=16, fontweight=’bold’) plt.axis(‘off’) plt.tight_layout() plt.show()
【描画関数の使い分け】 nx.draw() └── ノード、エッジ、ラベルをまとめて描画 より細かく制御したい場合は以下を個別に呼び出す: nx.draw_networkx_edges(G, pos, …) ├── エッジだけを描画 ├── alpha: 透明度(0〜1) └── 先に描画して背景に配置 nx.draw_networkx_nodes(G, pos, …) ├── ノードだけを描画 ├── cmap: カラーマップ(色の配色) └── node_colorに数値リストを渡すと自動で色分け nx.draw_networkx_labels(G, pos, …) ├── ラベルだけを描画 └── 最後に描画して前面に配置 【この順序の理由】 1. エッジ(背景) 2. ノード(中間) 3. ラベル(前面) → 見やすい重なり順になる

🔀 5. 有向グラフと重み付きグラフ

有向グラフ(方向性のあるグラフ)

SNSのフォロー関係のように、「AがBをフォローしている」けど「BはAをフォローしていない」という一方向の関係を表現するには有向グラフを使います。

# 有向グラフを作成 G = nx.DiGraph() # DiGraph = Directed Graph # フォロー関係(一方向) follows = [ (‘太郎’, ‘花子’), # 太郎が花子をフォロー (‘太郎’, ‘次郎’), # 太郎が次郎をフォロー (‘花子’, ‘太郎’), # 花子が太郎をフォロー(相互フォロー) (‘花子’, ‘美咲’), (‘次郎’, ‘花子’), (‘美咲’, ‘太郎’) ] G.add_edges_from(follows)
【有向グラフと無向グラフの違い】 無向グラフ: nx.Graph() ├── A-B と B-A は同じエッジ ├── 双方向の関係 └── 例: 友達関係、共著関係 有向グラフ: nx.DiGraph() ├── A→B と B→A は別のエッジ ├── 一方向の関係 └── 例: フォロー関係、リンク、引用 【相互フォローの表現】 ・(‘太郎’, ‘花子’) と (‘花子’, ‘太郎’) の両方を追加 ・矢印が双方向に向く
# 有向グラフの可視化 plt.figure(figsize=(10, 8)) pos = nx.spring_layout(G, k=2) nx.draw_networkx_nodes(G, pos, node_color=’lightblue’, node_size=2000) nx.draw_networkx_labels(G, pos, font_size=12, font_weight=’bold’) # 矢印付きエッジを描画 nx.draw_networkx_edges( G, pos, edge_color=’gray’, width=2, arrows=True, # 矢印を表示 arrowsize=20, # 矢印のサイズ arrowstyle=’->’, # 矢印のスタイル connectionstyle=’arc3,rad=0.1′ # エッジを少し曲げる ) plt.title(‘フォロー関係(有向グラフ)’, fontsize=16, fontweight=’bold’) plt.axis(‘off’) plt.tight_layout() plt.show()
【矢印付きエッジのパラメータ】 arrows=True └── エッジに矢印を表示 arrowsize=20 └── 矢印の大きさ(デフォルトは10程度) arrowstyle=’->’ ├── 矢印のスタイル ├── ‘->’: 標準の矢印 ├── ‘-|>’: 三角形の矢印 └── ‘fancy’: 装飾的な矢印 connectionstyle=’arc3,rad=0.1′ ├── エッジの曲がり具合 ├── rad=0: 直線 ├── rad=0.1: 少し曲がる └── 相互エッジが重ならないようにするため

重み付きグラフ(エッジに値があるグラフ)

都市間の距離や、通信量のように、エッジに重み(値)を持たせたグラフを重み付きグラフと呼びます。

# 重み付きグラフ(都市間の距離) G = nx.Graph() # エッジに重み(距離)を追加 edges_with_weights = [ (‘東京’, ‘名古屋’, 350), (‘東京’, ‘仙台’, 350), (‘東京’, ‘大阪’, 550), (‘名古屋’, ‘大阪’, 190), (‘大阪’, ‘広島’, 330), (‘大阪’, ‘福岡’, 550), (‘仙台’, ‘札幌’, 800) ] for city1, city2, distance in edges_with_weights: G.add_edge(city1, city2, weight=distance)
【重み付きエッジの追加】 G.add_edge(city1, city2, weight=distance) ├── weight: エッジの属性名(任意の名前でOK) ├── distance: 属性の値 └── 複数の属性も追加可能: weight=350, color=’red’ 【重みの取得】 G[city1][city2][‘weight’] └── エッジの重みを取得 【他の属性の例】 ・weight: 重み、距離、コスト ・capacity: 容量(フロー問題) ・label: ラベル(表示用)
# 重み付きグラフの可視化 plt.figure(figsize=(12, 10)) pos = nx.spring_layout(G, k=3) # ノード nx.draw_networkx_nodes(G, pos, node_color=’lightgreen’, node_size=2500) nx.draw_networkx_labels(G, pos, font_size=14, font_weight=’bold’) # エッジ(太さを距離に応じて変更) edges = G.edges() weights = [G[u][v][‘weight’] for u, v in edges] max_weight = max(weights) # 距離が短いほど太い線(関係が強い) edge_widths = [(max_weight – w) / 100 + 1 for w in weights] nx.draw_networkx_edges(G, pos, width=edge_widths, alpha=0.6, edge_color=’gray’) # エッジのラベル(距離を表示) edge_labels = nx.get_edge_attributes(G, ‘weight’) edge_labels = {k: f'{v}km’ for k, v in edge_labels.items()} nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=10) plt.title(‘都市間の距離ネットワーク’, fontsize=16, fontweight=’bold’) plt.axis(‘off’) plt.tight_layout() plt.show()
【重み付きエッジの可視化】 weights = [G[u][v][‘weight’] for u, v in edges] ├── 各エッジの重みをリスト化 └── 線の太さや色を決めるために使用 edge_widths = [(max_weight – w) / 100 + 1 for w in weights] ├── 重み(距離)が小さいほど太い線にする ├── max_weight – w: 逆転(近いほど大きい値) ├── / 100: スケール調整 └── + 1: 最小の太さを確保 nx.get_edge_attributes(G, ‘weight’) ├── 全エッジの’weight’属性を取得 └── 辞書形式: {(‘東京’, ‘名古屋’): 350, …} nx.draw_networkx_edge_labels(G, pos, edge_labels, …) ├── エッジにラベル(テキスト)を表示 └── 距離などの情報を可視化

📊 6. 中心性分析(重要なノードを見つける)

中心性とは

ネットワーク内でどのノードが重要かを数値化するのが中心性(Centrality)です。様々な指標があり、「重要さ」の定義によって使い分けます。

📊 主要な中心性指標
指標 意味 高いノードの特徴 関数
次数中心性 接続数の多さ 友達が多い人 degree_centrality()
媒介中心性 最短経路を通る頻度 橋渡し役、情報のハブ betweenness_centrality()
近接中心性 他のノードへの近さ 全体に近い位置にいる closeness_centrality()
固有ベクトル中心性 重要なノードとのつながり 影響力のある人の知り合い eigenvector_centrality()
# 中心性の計算 degree_cent = nx.degree_centrality(G) # 次数中心性 betweenness_cent = nx.betweenness_centrality(G) # 媒介中心性 # 結果を表示 print(“次数中心性(友達が多い人):”) for node, score in sorted(degree_cent.items(), key=lambda x: x[1], reverse=True)[:3]: print(f” {node}: {score:.3f}”) print(“\n媒介中心性(橋渡し役):”) for node, score in sorted(betweenness_cent.items(), key=lambda x: x[1], reverse=True)[:3]: print(f” {node}: {score:.3f}”)
【中心性の使い分け】 次数中心性(degree) ├── 単純に接続数をカウント ├── 使う場面: SNSのフォロワー数、論文の引用数 └── 「直接つながっている数」で重要度を測る 媒介中心性(betweenness) ├── 最短経路をどれだけ通過するか ├── 使う場面: 情報伝達の要、組織内のキーパーソン └── 「橋渡し役」としての重要度を測る 近接中心性(closeness) ├── 他の全ノードへの平均距離の逆数 ├── 使う場面: 情報が素早く届く位置にいるか └── 「全体への近さ」で重要度を測る 固有ベクトル中心性(eigenvector) ├── 重要なノードとつながっているか ├── 使う場面: GoogleのPageRank、影響力分析 └── 「重要な人の知り合い」としての重要度を測る

💼 7. 実務での活用例

例:組織内コミュニケーション分析

メールのやり取りをネットワーク化すると、誰がコミュニケーションのハブになっているか部門間の連携は十分かといった分析ができます。

※ コードが長い場合は横スクロールできます

import networkx as nx import matplotlib.pyplot as plt from matplotlib.patches import Patch # 組織内のメールのやり取り G = nx.DiGraph() # 部署情報 departments = { ‘山田’: ‘営業’, ‘佐藤’: ‘営業’, ‘鈴木’: ‘営業’, ‘田中’: ‘開発’, ‘伊藤’: ‘開発’, ‘渡辺’: ‘開発’, ‘高橋’: ‘管理’, ‘中村’: ‘管理’ } # コミュニケーション(送信者 → 受信者、頻度) communications = [ (‘山田’, ‘佐藤’, 50), (‘山田’, ‘鈴木’, 30), (‘山田’, ‘田中’, 20), (‘佐藤’, ‘山田’, 45), (‘佐藤’, ‘高橋’, 25), (‘鈴木’, ‘山田’, 35), (‘鈴木’, ‘伊藤’, 15), (‘田中’, ‘伊藤’, 60), (‘田中’, ‘渡辺’, 40), (‘伊藤’, ‘田中’, 55), (‘伊藤’, ‘中村’, 10), (‘渡辺’, ‘田中’, 35), (‘高橋’, ‘中村’, 30), (‘高橋’, ‘山田’, 20), (‘中村’, ‘高橋’, 28) ] for sender, receiver, frequency in communications: G.add_edge(sender, receiver, weight=frequency) # 部署ごとに色を設定 dept_colors = {‘営業’: ‘#E74C3C’, ‘開発’: ‘#3498DB’, ‘管理’: ‘#2ECC71’} node_colors = [dept_colors[departments[node]] for node in G.nodes()] # 可視化 plt.figure(figsize=(14, 10)) pos = nx.spring_layout(G, k=3, iterations=50) # エッジ(太さを頻度に応じて変更) edges = G.edges() weights = [G[u][v][‘weight’] for u, v in edges] max_weight = max(weights) edge_widths = [w / max_weight * 5 for w in weights] nx.draw_networkx_edges( G, pos, width=edge_widths, alpha=0.4, arrows=True, arrowsize=15, edge_color=’gray’, connectionstyle=’arc3,rad=0.1′ ) # ノード nx.draw_networkx_nodes(G, pos, node_color=node_colors, node_size=2000, alpha=0.9) # ラベル nx.draw_networkx_labels(G, pos, font_size=11, font_weight=’bold’) # 凡例 legend_elements = [ Patch(facecolor=’#E74C3C’, label=’営業部’), Patch(facecolor=’#3498DB’, label=’開発部’), Patch(facecolor=’#2ECC71′, label=’管理部’) ] plt.legend(handles=legend_elements, loc=’upper right’, fontsize=12) plt.title(‘組織内コミュニケーション分析\n(線の太さ=メール頻度)’, fontsize=16, fontweight=’bold’) plt.axis(‘off’) plt.tight_layout() plt.show() # 中心人物を特定 betweenness = nx.betweenness_centrality(G) print(“\n【分析結果】中心人物(媒介中心性):”) for person, score in sorted(betweenness.items(), key=lambda x: x[1], reverse=True)[:3]: print(f” {person}({departments[person]}): {score:.3f}”)
【このコードでわかること】 1. 部門内のコミュニケーション ・同じ色のノード間のエッジが多いか確認 ・部門内で孤立している人はいないか 2. 部門間の連携 ・異なる色のノード間にエッジがあるか ・部門間の橋渡し役は誰か 3. 情報のボトルネック ・媒介中心性が高い人 = 情報の要 ・その人が抜けると情報が滞る可能性 【凡例の作り方】 from matplotlib.patches import Patch ├── Patchオブジェクトで色見本を作成 └── plt.legend()で凡例として表示

📝 STEP 27 のまとめ

✅ このステップで学んだこと
トピック 重要ポイント
ネットワーク図の基礎 ノード(点)とエッジ(線)で関係性を表現
NetworkXの基本 nx.Graph()でグラフ作成、add_node/add_edge
レイアウト spring_layout(バネモデル)が最も一般的
グラフの種類 無向/有向/重み付きを目的に応じて選択
カスタマイズ ノードのサイズ・色でデータを表現
中心性分析 次数/媒介/近接/固有ベクトル中心性
💡 最重要ポイント

ネットワーク図は、複雑な関係性を一目で理解できる強力なツールです。

ノードのサイズや色で重要度を表現
エッジの太さで関係の強さを表現
中心性分析でキーパーソンを発見
レイアウトは目的に応じて選択

ただし、ノードが50を超えると見づらくなるため、フィルタリングやグループ化を検討しましょう。次のステップでは、ダッシュボードデザインの原則を学びます!

📝 実践演習

演習 1 基礎

5つのノード(A, B, C, D, E)と6つのエッジを持つ簡単なネットワーク図を作成してください。

import networkx as nx import matplotlib.pyplot as plt # グラフ作成 G = nx.Graph() G.add_edges_from([ (‘A’, ‘B’), (‘B’, ‘C’), (‘C’, ‘D’), (‘D’, ‘E’), (‘E’, ‘A’), (‘A’, ‘C’) ]) # 可視化 plt.figure(figsize=(8, 6)) nx.draw( G, with_labels=True, node_color=’lightblue’, node_size=1500, font_size=16, font_weight=’bold’ ) plt.title(‘シンプルなネットワーク図’) plt.axis(‘off’) plt.show()

ポイント:add_edges_from()でエッジを追加すると、ノードも自動的に追加されます。

演習 2 応用

有向グラフを作成し、矢印付きで表示してください(フォロー関係をイメージ)。

import networkx as nx import matplotlib.pyplot as plt # 有向グラフ作成 G = nx.DiGraph() G.add_edges_from([ (‘太郎’, ‘花子’), (‘花子’, ‘太郎’), # 相互フォロー (‘太郎’, ‘次郎’), (‘次郎’, ‘美咲’), (‘美咲’, ‘花子’) ]) # 可視化 plt.figure(figsize=(10, 8)) pos = nx.spring_layout(G, k=2) nx.draw_networkx_nodes(G, pos, node_color=’lightgreen’, node_size=2000) nx.draw_networkx_labels(G, pos, font_size=12, font_weight=’bold’) nx.draw_networkx_edges( G, pos, arrows=True, arrowsize=20, arrowstyle=’->’, edge_color=’gray’, width=2, connectionstyle=’arc3,rad=0.1′ ) plt.title(‘フォロー関係(有向グラフ)’) plt.axis(‘off’) plt.show()

ポイント:nx.DiGraph()で有向グラフを作成し、arrows=Trueで矢印を表示します。connectionstyle=’arc3,rad=0.1’で相互エッジが重ならないよう曲げています。

演習 3 発展

重み付きグラフを作成し、エッジの太さを重みに応じて変化させてください。さらにエッジにラベル(重みの値)を表示してください。

import networkx as nx import matplotlib.pyplot as plt # 重み付きグラフ作成 G = nx.Graph() edges = [ (‘A’, ‘B’, 10), (‘B’, ‘C’, 5), (‘C’, ‘D’, 15), (‘D’, ‘A’, 8), (‘A’, ‘C’, 12) ] for u, v, w in edges: G.add_edge(u, v, weight=w) # 可視化 plt.figure(figsize=(10, 8)) pos = nx.spring_layout(G, k=2) # エッジの太さを計算 weights = [G[u][v][‘weight’] for u, v in G.edges()] max_w = max(weights) widths = [w / max_w * 10 for w in weights] # 描画 nx.draw_networkx_nodes(G, pos, node_color=’lightcoral’, node_size=2000) nx.draw_networkx_labels(G, pos, font_size=14, font_weight=’bold’) nx.draw_networkx_edges(G, pos, width=widths, alpha=0.6, edge_color=’gray’) # エッジラベル edge_labels = nx.get_edge_attributes(G, ‘weight’) nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=12) plt.title(‘重み付きグラフ(線の太さ=重み)’) plt.axis(‘off’) plt.show()

ポイント:G.add_edge(u, v, weight=w)で重みを追加。nx.get_edge_attributes()で重みを取得し、nx.draw_networkx_edge_labels()でラベル表示します。

❓ よくある質問

Q1: ノードが多すぎて見づらいです。どうすればいいですか?
以下の方法を試してください:
フィルタリング:重要なノード(次数が高いなど)だけ表示
グループ化:コミュニティ検出でグループに分割
インタラクティブ化:Plotlyでズーム機能を追加
階層化:重要度に応じて段階的に表示
一般的に、50ノードを超えると見づらくなります。
Q2: レイアウトがきれいに配置されません。どうすればいいですか?
spring_layoutのパラメータを調整しましょう:
pos = nx.spring_layout(G, k=2, iterations=100, seed=42)
k:ノード間の距離(大きいほど離れる)
iterations:計算回数(多いほど最適化)
seed:乱数シード(毎回同じレイアウトにする)
また、他のレイアウト(circular、kamada_kawai)も試してみてください。
Q3: ネットワークの中心人物を見つけるにはどうすればいいですか?
中心性指標を計算しましょう:
次数中心性:nx.degree_centrality(G) – つながりの数
媒介中心性:nx.betweenness_centrality(G) – 橋渡し役
近接中心性:nx.closeness_centrality(G) – 全体への近さ
固有ベクトル中心性:nx.eigenvector_centrality(G) – 重要な人とのつながり
目的に応じて適切な指標を選んでください。
Q4: ネットワーク内のグループ(コミュニティ)を見つけるには?
コミュニティ検出アルゴリズムを使います:
from networkx.algorithms.community import greedy_modularity_communities
communities = greedy_modularity_communities(G)
これにより、密につながったノードのグループを自動で検出できます。検出されたコミュニティごとに色分けすると、ネットワークの構造が見えてきます。
Q5: ネットワーク図を画像として保存するには?
plt.savefig()を使います:
plt.savefig('network.png', dpi=300, bbox_inches='tight')
dpi=300:解像度(印刷用は300以上推奨)
bbox_inches=’tight’:余白を最小限に
plt.show()の前に記述してください。PDF形式にも対応しています。
📝

学習メモ

データ可視化マスター - Step 27

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE