メモ_Pythonでグラフ構造のダミーデータを生成しjsonで保存して関係図を描画する

Pythonでグラフ構造のダミーデータを生成しjsonで保存して関係図を描画するまでの一連のメモです。コード例も。

 

ダミーデータ生成:

以下のような仕様でダミーデータを生成します。

 

ノード : User_id
エッジ : relative、friend、acquaintance
プロパティ : 氏名、年齢、性別、所在地(都道府県)

 

生成するダミーデータの最大数と、各ノードが持つエッジの最大数も指定します。

コード例:

import networkx as nx
from faker import Faker
import random

# ダミーデータ生成のための初期設定
fake = Faker('ja_JP')
G = nx.Graph()

# ノードとエッジの数
num_nodes = 10
max_edges_per_node = 5

# ノードを生成してグラフに追加
for _ in range(num_nodes):
    user_id = fake.unique.random_int(min=1, max=1000000)
    name = fake.name()
    age = fake.random_int(min=18, max=80)
    gender = fake.random_element(elements=('man', 'woman'))
    location = fake.prefecture()
    
    G.add_node(user_id, name=name, age=age, gender=gender, location=location)

# エッジを生成してノードに追加
for node in G.nodes:
    num_edges = random.randint(1, max_edges_per_node)
    edges_to_add = random.sample(G.nodes, num_edges)
    
    for neighbor in edges_to_add:
        if neighbor != node:
            relationship = fake.random_element(elements=('relative', 'friend', 'acquaintance'))
            G.add_edge(node, neighbor, relationship=relationship)

# グラフを表示
print(f"ノード数: {len(G.nodes)}")
print(f"エッジ数: {len(G.edges)}")

# 例として最初のノードの情報を表示
first_node = list(G.nodes)[0]
print(f"最初のノードの情報: {G.nodes[first_node]}")


    
結果

以下のように成功しました。生成数が控えめなのは、後で関係図を描画する際にノードが多いと見づらいためで、1万でも10万でも生成できました。

生成したダミーのグラフ構造データをjsonに保存する

以下のコードでjsonに保存します


import json

# ダミーデータを辞書に変換
data = {
    "nodes": [],
    "edges": []
}

for node in G.nodes:
    node_data = {
        "user_id": node,
        "name": G.nodes[node]["name"],
        "age": G.nodes[node]["age"],
        "gender": G.nodes[node]["gender"],
        "location": G.nodes[node]["location"]
    }
    data["nodes"].append(node_data)

for edge in G.edges:
    edge_data = {
        "source": edge[0],
        "target": edge[1],
        "relationship": G.edges[edge]["relationship"]
    }
    data["edges"].append(edge_data)

# データをJSONファイルに保存
with open("dummy_data.json", "w") as json_file:
    json.dump(data, json_file, indent=4)

print("ダミーデータをJSONファイルに保存しました。")

    
結果

無事にjsonデータで保存できました。石川翔太なのにwomanとなってしまっているのはご愛敬。

グラフ構造データを描画する

生成されたダミーデータをjsonから読み込んでmatplotlibで描画してみます


import networkx as nx
import matplotlib.pyplot as plt
import json
import japanize_matplotlib  # japanize-matplotlibをインポート

# JSONファイルからダミーデータを読み込む
with open("dummy_data.json", "r") as json_file:
    data = json.load(json_file)

# NetworkXグラフを作成
G = nx.Graph()

# ノードを追加
for node_data in data["nodes"]:
    G.add_node(node_data["user_id"], **node_data)

# エッジを追加
for edge_data in data["edges"]:
    G.add_edge(edge_data["source"], edge_data["target"], relationship=edge_data["relationship"])

# 関係図を描画
pos = nx.spring_layout(G, seed=42)  # グラフのレイアウトを決定
fig, ax = plt.subplots(figsize=(12, 12))  # 図のサイズを設定

# エッジの関係ラベルを表示
edge_labels = nx.get_edge_attributes(G, 'relationship')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=14, font_color='red')

# ノードとエッジを描画
nx.draw(G, pos, with_labels=True, node_size=300, font_size=14, font_color='black', node_color='lightblue', edge_color='gray', width=0.5, ax=ax)

plt.title("関係図")
plt.axis("off")  # 軸を非表示にする
plt.show()

    
結果

以下のように成功しました。font-sizeは見やすいように少し大きめに設定してます。