1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Fakerの拡張プロバイダを自作して親子関係のあるデータを生成するテクニック

Posted at

はじめに

image.png

データ生成ライブラリとして有名な Faker を活用して、親子関係のあるデータ を自由自在に生成する方法を紹介します。

例えば、以下のようなケースに対応できます。

  • 顧客 (Parent) と 注文 (Child)
    • customer_id をキーとして、 orderscustomer_id を持たせる
  • 商品カテゴリ (Parent) と サブカテゴリ (Child)
    • category_id をキーとして、 sub_categoriesparent_category_id を設定
  • ブログのユーザ (Parent) と 記事 (Child)
    • user_id をキーとして、 postsuser_id を持たせる

Faker の標準機能だけでは対応しきれないため、カスタムプロバイダ を作成する方法を解説します。


環境設定

  • Python 3.x (この記事では 3.9 以上を想定)
  • Faker ライブラリ
  • Google Colab やローカルの Python 環境
pip install Faker

Google Colab では、ノートブックの最初のセルで上記コマンドを実行してください。


方法 1: 親子をセットで生成する

親1レコードと子Nレコードをまとめて生成 するカスタムプロバイダを作成します。

image.png

実装

from faker import Faker
from faker.providers import BaseProvider
import random
from datetime import datetime

fake = Faker()
fake.seed_instance(1234)

class ParentAndChildDataProvider(BaseProvider):
    def create_parent_with_children(self, num_children=3):
        """
        親1件、子N件を生成し、親のIDを子に紐づける
        """
        parent_id = f"CUST-{random.randint(1000,9999)}"
        parent_data = {
            "customer_id": parent_id,
            "customer_name": fake.name(),
            "registered_date": fake.date_between('-1y', 'today')
        }

        children_data = []
        for _ in range(num_children):
            order_id = f"ORD-{random.randint(10000,99999)}"
            order_date = fake.date_between(start_date=parent_data['registered_date'], end_date='today')
            total_amount = random.randint(1000, 20000)

            child = {
                "order_id": order_id,
                "customer_id": parent_id,
                "order_date": order_date,
                "total_amount": total_amount,
            }
            children_data.append(child)

        return {
            "parent": parent_data,
            "children": children_data
        }

# プロバイダ追加
fake.add_provider(ParentAndChildDataProvider)

# 実行例
print(fake.create_parent_with_children(num_children=3))

方法 2: 先に親を生成し、子を後で割り当てる

image.png

データベースのように 親リストを先に作成 し、後で 子データを親に紐づける 方法です。

実装

class ParentChildSeparateProvider(BaseProvider):
    def create_parents(self, n=5):
        """ 親データを n 件生成 """
        parent_list = []
        for _ in range(n):
            parent_id = f"CUST-{random.randint(1000,9999)}"
            parent = {
                "customer_id": parent_id,
                "customer_name": fake.name(),
                "registered_date": fake.date_between('-1y', 'today')
            }
            parent_list.append(parent)
        return parent_list

    def create_children(self, parents, num_children=3):
        """ 既存の親データを参照しながら、子データを生成 """
        children_list = []
        for _ in range(num_children):
            parent = random.choice(parents)
            order_id = f"ORD-{random.randint(10000,99999)}"
            order_date = fake.date_between(start_date=parent['registered_date'], end_date='today')
            total_amount = random.randint(1000, 20000)

            child = {
                "order_id": order_id,
                "customer_id": parent["customer_id"],
                "order_date": order_date,
                "total_amount": total_amount,
            }
            children_list.append(child)
        return children_list

# プロバイダ追加
fake.add_provider(ParentChildSeparateProvider)

# 親データを10件生成
parents_data = fake.create_parents(n=10)
print(f"--- Parents ---\n{parents_data}\n")

# 子データを20件生成し、親IDをランダムに割り当て
children_data = fake.create_children(parents=parents_data, num_children=20)
print(f"--- Children ---")
for c in children_data:
    print(c)

まとめ

image.png

  • Faker のカスタムプロバイダを利用して、親子関係のあるデータを簡単に生成できる
  • 親と子をセットで生成する方法親リストを先に作って子に紐づける方法 の2パターンを紹介
  • 実データに近い 外部キーのような制約 を持ったモックデータを作れる

これを活用すれば、テストデータや開発時のモックデータ生成がスムーズになります。ぜひ活用してみてください!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?