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は見やすいように少し大きめに設定してます。