簡単にサンプルデータを生成するPythonのライブラリ「faker」
AWS事業本部コンサルティング部の石川です。プログラム開発では、テストやデモ用のサンプルデータが必要になることがよくあります。そんな時に便利なのが、Pythonのライブラリ「faker」 です。fakerを使えば、名前、住所、電話番号など、様々な種類のサンプルデータを簡単に作成できます。
最近だと生成AIを使って作成することが多くなってきましたが、ある程度大きなデータを効率よく作成するにはfakerのようなライブラリは使い勝手が良いはずです。
私と「faker」の出会いは、AWSの関山さんも共同執筆している AWS Big Data Blog 「AWS Glue Data Catalog supports automatic optimization of Apache Iceberg tables through your Amazon VPC」のCloudformation テンプレートの中のサンプルプログラムでした。試しで色々実行したところ日本語のサンプルデータも作成できてテンションが上ってしまいました。
fakerのインストール
以下のコマンドでfakerをインストールします。
pip install faker
実行例
% pip install faker
Collecting faker
Downloading Faker-33.1.0-py3-none-any.whl.metadata (15 kB)
Requirement already satisfied: python-dateutil>=2.4 in /Users/ishikawa.satoru/.pyenv/versions/3.11.10/lib/python3.11/site-packages (from faker) (2.9.0.post0)
Requirement already satisfied: typing-extensions in /Users/ishikawa.satoru/.pyenv/versions/3.11.10/lib/python3.11/site-packages (from faker) (4.12.2)
Requirement already satisfied: six>=1.5 in /Users/ishikawa.satoru/.pyenv/versions/3.11.10/lib/python3.11/site-packages (from python-dateutil>=2.4->faker) (1.17.0)
Downloading Faker-33.1.0-py3-none-any.whl (1.9 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.9/1.9 MB 2.7 MB/s eta 0:00:00
Installing collected packages: faker
Successfully installed faker-33.1.0
基本的な使い方
fakerの基本的な使い方は非常に簡単です。以下のようにして、Fakerオブジェクトを作成し、各種メソッドを呼び出すだけです。
from faker import Faker
fake = Faker()
print(fake.name())
print(fake.address())
print(fake.email())
実行例
% python faker_sample.py
Tammy Gillespie
021 Louis Drive Apt. 759
Gonzalezbury, DE 58333
jennifer67@example.org
更にfakerは多言語に対応しており、日本語のサンプルデータも生成できます。日本語データを生成するには、Fakerオブジェクトを作成する際にロケールを指定します。
from faker import Faker
fake = Faker('ja_JP') # 日本語のデータを生成
print(fake.name())
print(fake.address())
print(fake.email())
実行例
% python faker_sample.py
石川 英樹
宮城県東村山市山中新田41丁目16番13号
rnakagawa@example.net
多様なデータを生成をサポート
Pythonのライブラリ「faker」には、多様なオプションが用意されており、様々な種類のダミーデータを生成することができます。以下に主要なオプションです。
個人情報
fake.name()
: フルネームを生成fake.address()
: 住所を生成fake.phone_number()
: 電話番号を生成fake.email()
: メールアドレスを生成
テキスト
fake.word()
: 単語を生成fake.sentence()
: 文を生成fake.paragraph()
: 段落を生成fake.text()
: テキストを生成
インターネット関連
fake.user_agent()
: ユーザーエージェントを生成fake.chrome()
: Chromeのユーザーエージェントを生成fake.firefox()
: Firefoxのユーザーエージェントを生成fake.safari()
: Safariのユーザーエージェントを生成
その他
fake.boolean()
: ブール値を生成fake.date()
: 日付を生成fake.time()
: 時間を生成fake.company()
: 会社名を生成fake.job()
: 職業名を生成
プロファイル生成
fake.profile()
を使用すると、複数の情報を含むプロファイルを一度に生成できます。
fake.profile(fields=['name', 'address', 'birthdate', 'job'])
これをprintすると下記のように出力します。
{'job': 'モデル', 'name': '佐々木 春香', 'address': '千葉県武蔵野市所野29丁目12番3号', 'birthdate': datetime.date(1938, 8, 9)}
fackerコマンド
Pythonライブラリだけでなく、fackerコマンドも一緒にインストールされます。ちょっとしたCSVとかならこれで十分かもしれません。
faker name
faker address
faker -r 3 -s ";" name # 3つの名前をセミコロン区切りで生成
オプションは以下のとおりです。
% faker --help
usage: faker [-h] [--version] [-v] [-o output] [-l LOCALE] [-r REPEAT]
[-s SEP] [--seed SEED] [-i [INCLUDE ...]]
[fake] [fake argument ...]
faker version 33.1.0
positional arguments:
fake name of the fake to generate output for (e.g. profile)
fake argument optional arguments to pass to the fake (e.g. the
profile fake takes an optional list of comma separated
field names as the first argument)
options:
-h, --help show this help message and exit
--version show program's version number and exit
-v, --verbose show INFO logging events instead of CRITICAL, which is
the default. These logging events provide insight into
localization of specific providers.
-o output redirect output to a file
-l LOCALE, --lang LOCALE
specify the language for a localized provider (e.g.
de_DE)
-r REPEAT, --repeat REPEAT
generate the specified number of outputs
-s SEP, --sep SEP use the specified separator after each output
--seed SEED specify a seed for the random generator so that
results are repeatable. Also compatible with 'repeat'
option
-i [INCLUDE ...], --include [INCLUDE ...]
list of additional custom providers to user, given as
the import path of the module containing your Provider
class (not the provider class itself)
supported locales:
ar_AA, ar_AE, ar_BH, ar_EG, ar_JO, ar_PS, ar_SA, az_AZ, bg_BG, bn_BD, bs_BA, cs_CZ, da_DK, de, de_AT, de_CH, de_DE, dk_DK, el_CY, el_GR, en, en_AU, en_BD, en_CA, en_GB, en_IE, en_IN, en_MS, en_NZ, en_PH, en_PK, en_TH, en_US, es, es_AR, es_CA, es_CL, es_CO, es_ES, es_MX, et_EE, fa_IR, fi_FI, fil_PH, fr_BE, fr_CA, fr_CH, fr_FR, fr_QC, ga_IE, gu_IN, he_IL, hi_IN, hr_HR, hu_HU, hy_AM, id_ID, it_CH, it_IT, ja_JP, ka_GE, ko_KR, la, lb_LU, lt_LT, lv_LV, mt_MT, ne_NP, nl_BE, nl_NL, no_NO, or_IN, pl_PL, pt_BR, pt_PT, ro_RO, ru_RU, sk_SK, sl_SI, sq_AL, sv_SE, sw, ta_IN, th, th_TH, tl_PH, tr_TR, tw_GH, uk_UA, uz_UZ, vi_VN, yo_NG, zh_CN, zh_TW, zu_ZA
Faker can take a locale as an optional argument, to return localized data. If
no locale argument is specified, the factory falls back to the user's OS
locale as long as it is supported by at least one of the providers.
- for this user, the default locale is ja_JP.
If the optional argument locale and/or user's default locale is not available
for the specified provider, the factory falls back to faker's default locale,
which is en_US.
examples:
$ faker address
968 Bahringer Garden Apt. 722
Kristinaland, NJ 09890
$ faker -l de_DE address
Samira-Niemeier-Allee 56
94812 Biedenkopf
$ faker profile ssn,birthdate
{'ssn': u'628-10-1085', 'birthdate': '2008-03-29'}
$ faker -r=3 -s=";" name
Willam Kertzmann;
Josiah Maggio;
Gayla Schmitt;
応用例
企業情報サンプル
from faker import Faker
from datetime import datetime
fake = Faker()
def generate_company_data(num_companies):
companies = []
for _ in range(num_companies):
company = {
'name': fake.company(),
'catch_phrase': fake.catch_phrase(),
'address': fake.address(),
'website': fake.url(),
'employee_count': fake.random_int(min=10, max=1000)
}
companies.append(company)
return companies
company_data = generate_company_data(5)
for company in company_data:
print(company)
実行例
{'name': 'Webb-Collins', 'catch_phrase': 'Inverse content-based groupware', 'address': 'Unit 7676 Box 2382\nDPO AP 78501', 'website': 'https://www.smith-morton.com/', 'employee_count': 39}
{'name': 'Moore, Robertson and Davis', 'catch_phrase': 'Self-enabling interactive product', 'address': '39730 Mark Oval\nLake Dariusport, CA 96309', 'website': 'http://wise.com/', 'employee_count': 627}
{'name': 'Singh-Mccann', 'catch_phrase': 'Virtual uniform capability', 'address': '6705 Maxwell Trail Suite 563\nEast Sherri, CO 02637', 'website': 'http://brown.com/', 'employee_count': 750}
{'name': 'Mckinney, Mathews and Armstrong', 'catch_phrase': 'Polarized context-sensitive collaboration', 'address': '88155 Juarez Bridge\nNew Jennifer, FM 25694', 'website': 'http://reynolds.org/', 'employee_count': 977}
{'name': 'Anderson-Roy', 'catch_phrase': 'Expanded regional capacity', 'address': '49299 Katrina Station\nEast Taramouth, WV 44486', 'website': 'http://www.jackson-young.com/', 'employee_count': 280}
金融取引サンプル
from faker import Faker
from datetime import datetime
fake = Faker()
def generate_transactions(num_transactions):
transactions = []
start_date = datetime(2023, 1, 1)
end_date = datetime(2023, 12, 31)
for _ in range(num_transactions):
transaction = {
'date': f"{fake.date_between(start_date=start_date, end_date=end_date)}",
'amount': round(fake.random.uniform(10, 1000), 2),
'description': fake.bs(),
'category': fake.random_element(elements=('Food', 'Transport', 'Entertainment', 'Utilities', 'Shopping'))
}
transactions.append(transaction)
return sorted(transactions, key=lambda x: x['date'])
fake_transactions = generate_transactions(5)
for transaction in fake_transactions:
print(transaction)
実行例
{'date': '2023-01-07', 'amount': 465.16, 'description': 'grow one-to-one e-services', 'category': 'Transport'}
{'date': '2023-02-01', 'amount': 787.54, 'description': 'integrate scalable methodologies', 'category': 'Food'}
{'date': '2023-02-10', 'amount': 110.6, 'description': 'iterate strategic mindshare', 'category': 'Food'}
{'date': '2023-03-22', 'amount': 220.29, 'description': 'reinvent proactive mindshare', 'category': 'Shopping'}
{'date': '2023-05-29', 'amount': 244.21, 'description': 'whiteboard B2C infrastructures', 'category': 'Entertainment'}
商品カタログサンプル
from faker import Faker
from datetime import datetime
fake = Faker()
def generate_product_catalog(num_products):
catalog = []
for _ in range(num_products):
product = {
'name': fake.catch_phrase(),
'description': fake.text(max_nb_chars=200),
'price': round(fake.random.uniform(10, 500), 2),
'category': fake.random_element(elements=('Electronics', 'Clothing', 'Home & Garden', 'Books', 'Toys')),
'sku': fake.ean(length=13)
}
catalog.append(product)
return catalog
product_catalog = generate_product_catalog(5)
for product in product_catalog:
print(product)
実行例
{'name': 'Streamlined scalable contingency', 'description': 'Improve benefit morning lose enough nor station. Respond tax example sister cost. Agency generation ready anything.', 'price': 199.07, 'category': 'Clothing', 'sku': '9128152314040'}
{'name': 'Reverse-engineered static groupware', 'description': 'Heavy class finish. Best agent believe work. Big throughout vote suggest on true owner.\nMatter to economy tax front table character. Challenge television contain set pass.', 'price': 202.08, 'category': 'Electronics', 'sku': '2656143964600'}
{'name': 'De-engineered human-resource projection', 'description': 'Apply care set plan. Meet certain determine stay.\nPattern really step why number thing gas sound. Inside point rich method quite window. Key do benefit.', 'price': 335.43, 'category': 'Books', 'sku': '4708567544178'}
{'name': 'Seamless directional open architecture', 'description': 'Who bad hit treatment president money. Say yourself society perform when modern production. Say cup push everything protect capital information attack.', 'price': 466.55, 'category': 'Books', 'sku': '2993136285954'}
{'name': 'Compatible next generation definition', 'description': 'Policy establish wall usually avoid. Answer forward might Mrs. Identify research production interview without the. Yeah television laugh treat federal employee.', 'price': 296.92, 'category': 'Clothing', 'sku': '9997702672066'}
実用サンプル
CSVファイルの生成
一番最初にやりたかったのがこれです、大量のダミーデータをCSVファイルとして出力することも可能です。
import csv
from faker import Faker
fake = Faker('ja_JP')
with open('sample_data.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['名前', '住所', '電話番号'])
for _ in range(5):
writer.writerow([fake.name(), fake.address(), fake.phone_number()])
実行例(sample_data.csv)
名前,住所,電話番号
田中 智也,山口県三宅島三宅村明石町25丁目25番16号 アーバン長間554,070-7566-1557
森 翔太,岩手県川崎市幸区浅草19丁目10番19号,090-2866-8956
福田 裕樹,佐賀県川崎市高津区西神田18丁目18番3号 富久町シティ851,080-1853-7056
山田 裕太,大阪府君津市明石町5丁目12番15号 パレス丸の内349,73-7863-4597
岡田 太郎,千葉県利島村台場20丁目9番14号,080-1785-6615
例えば、デリミタをタブ区切りに変更したい場合は、下記のように書き換えます。
writer = csv.writer(f, delimiter='\t')
JSONファイルの生成
大量のダミーデータをJSONファイル(正確には、jsonl)として出力することも可能です。
from faker import Faker
fake = Faker('ja_JP')
with open('sample_data.jsonl', 'w', encoding='utf-8') as f:
for _ in range(5):
user = {
'name': fake.name(),
'address': fake.address(),
'email': fake.email(),
'dob': f'{fake.date_of_birth(minimum_age=18, maximum_age=80)}',
'phone': fake.phone_number()
}
print(user, file=f)
実行例(sample_data.jsonl)
{'name': '小川 陽一', 'address': '兵庫県山武郡九十九里町南郷屋39丁目26番7号 芝公園クレスト912', 'email': 'ryohei29@example.org', 'dob': '1955-07-01', 'phone': '080-8424-0382'}
{'name': '渡辺 千代', 'address': '京都府新宿区押上1丁目27番1号 東上野クレスト629', 'email': 'yamaguchinanami@example.org', 'dob': '1977-04-25', 'phone': '080-0229-1025'}
{'name': '佐藤 太郎', 'address': '京都府足立区九段南15丁目20番1号', 'email': 'mikiyoshida@example.org', 'dob': '1977-08-03', 'phone': '07-1853-2477'}
{'name': '中村 裕美子', 'address': '大分県君津市京橋4丁目21番17号 シティ竜泉650', 'email': 'haruka74@example.org', 'dob': '1983-07-21', 'phone': '24-5977-9758'}
{'name': '遠藤 洋介', 'address': '高知県神津島村中宮祠18丁目18番7号', 'email': 'tsubasayamamoto@example.org', 'dob': '1952-05-31', 'phone': '06-8649-2618'}
最後に
Pythonのライブラリfakerは、テストやデモ用のサンプルデータを簡単に生成できる強力なツールです。名前、住所、電話番号、メールアドレスなど、多岐にわたるデータ型に対応しており、日本語を含む多言語サポートも充実しています。コマンドラインツールとしても使用でき、CSVやJSONファイルのサンプルデータも簡単に作成できます。
ランダムで出力するファイルはどこにあるかというと、providersフォルダ配下の末端のファイル(__init__.py)の中にハードコードされています。例えば、日本人の名前であればこのファイルです。
私にとっては新しいツールだったのですが、GitHubのタイムスタンプは10年前だったので、昔からあるからーって人は、スルーしてください。