Pythonでそれっぽいテストデータを作成する(前編)

Twitterでダミーデータ作成するPHP版の[Faker](https://github.com/fzaninotto/Faker)とやらをを教えて貰ったので、Pyhton版を探したら案の定あったのでインストールしてみました。

# インストール
```
% pip install faker
% faker --version
faker 4.0.2
```
# お試しデータ作成
```make_fake_data.py
from faker.factory import Factory

Faker = Factory.create
fake = Faker()
fake.seed(0)
fake = Faker("ja_JP")

print(
    fake.csv(
        header=None,
        data_columns=("{{name}}", "{{zipcode}}", "{{address}}", "{{phone_number}}"),
        num_rows=10,
        include_row_ids=False,
    )
)
```
VS Codeのデバッグモードで実行してみます。

```
 %  env PTVSD_LAUNCHER_PORT=53546 /usr/local/opt/python/bin/python3.7 /Users/nandymak/.vscode/extensions/ms-python.python-2020.2.64397/pythonFiles/lib/python/new_ptvsd/wheels/ptvsd/launcher /Users/nandymak/dev/fake-data/make_fake_data.py 
"藤本 直子","265-8376","大分県横浜市西区三筋23丁目19番7号 五味ヶ谷コーポ948","92-4115-7815"
"渚 亮介","989-9052","佐賀県長生郡白子町富久町36丁目1番3号 白金アーバン097","53-5139-3328"
"伊藤 聡太郎","520-8016","京都府西多摩郡瑞穂町九段南35丁目7番20号","090-4719-6593"
"加藤 健一","627-4260","秋田県新島村雷門3丁目27番3号 千束コート684","090-3396-9477"
"渡辺 陽子","812-5855","奈良県江戸川区丸の内ＪＰタワー13丁目8番1号","090-1352-5601"
"山岸 くみ子","836-9402","宮崎県国分寺市長畑8丁目21番7号 一ツ橋パーク510","090-3217-3008"
"井上 翔太","226-1179","石川県印旛郡栄町五味ヶ谷3丁目20番4号 芝浦アーバン792","090-3022-5841"
"笹田 加奈","482-6715","長崎県横浜市瀬谷区六番町25丁目27番9号 ハイツ港南150","090-2375-9459"
"中津川 舞","732-5083","長野県東久留米市丹勢13丁目23番11号 前弥六コーポ960","080-9602-7142"
"山田 亮介","618-0001","三重県千代田区平須賀27丁目7番18号 コート丸の内ＪＰタワー206","65-0300-8913"
```

それっぽいデータが作成されました。
余りにそれっぽいので会社で使うときは、Fakerで生成したダミーデータと前もって言っておかないと、個人情報の流出と大騒ぎになるかも知れません。

## CSV以外にも
TSVとか、DSV？などもあるようです。
使える機能を整理しないといけませんね(TODO)。

```faker.py
fake.tsv(header=None, data_columns=('{{name}}', '{{address}}'), num_rows=10, include_row_ids=False)
```


## 気づいた点
* 郵便番号と住所は関連付けられて生成されていません(当たり前ですが)<br>
 [「Fakerのダミーデータの漢字名とカナ名を一致させる」](https://qiita.com/nightyknite/items/42185be38bc1d5aa477e)って事を考えている方もいらっしゃいます。<br>
郵便番号と住所も工夫すれば出来そうですね。
* 電話番号は携帯電話の番号はそれっぽいですが、固定電話(ぽい)番号は前ゼロが落ちていたりして少しおかしいですね。

## 指定できる項目
表で纏めようと思いましたが200個以上あるようなので断念しました。
[PythonにてFakerを用いてテストデータを生成する方法](https://www.nblog09.com/w/2019/01/24/python-faker/)

取り敢えずよく使いそうなものをいくつか整理しておきます。
全リストは多分、公式サイトの[Docs » Locales » Language ja_JP](https://faker.readthedocs.io/en/master/locales/ja_JP.html)を見れば判ると思います。

### 住所系(faker.providers.address)
| メソッド名      | 意味             | サンプル                                           |
|-----------------|-------------------------|----------------------------------------------------|
| address         | 住所             | 熊本県八丈島八丈町平須賀38丁目9番5号 千塚パレス161 |
| ban             | 番地             | 6番                                                |
| building_name   | ビル名           | パーク                                             |
| building_number | ビル番号？       | 263                                                |
| chome           | 丁目             | 1丁目                                              |
| city            | 市町村           | 狛江市                                             |
| city_suffix     | 市町村(固定値？) | Ville                                              |
| country         | 国               | ニューカレドニア                                   |
| gou             | 号番             | 15号                                               |
| postcode        | 郵便番号         | 288-2290                                           |
| prefecture      | 都道府県名       | 栃木県                                             |
| street_address  | 番地             | 215 木村 Street                                    |
| street_name     | 通り名           | 佐々木 Street                                      |
| street_suffix   | 通りの接尾辞(※1) | Street                                             |
| town            | 町名             | 台場                                               |
| zipcode         | 郵便番号         | 149-3866                                           |

※1：通りをさらに説明するために通りの名前に続く単語

### 人名系(faker.providers.person)
| メソッド名                  | 意味                 | サンプル      |
|-----------------------------|----------------------|---------------|
| name                        | 氏名(漢字)           | 青山 結衣     |
| last_name                   | 苗字(漢字)           | 高橋          |
| first_name                  | 名前(漢字)           | 裕美子        |
| name_female                 | 女性の氏名(漢字)     | 田辺 知実     |
| name_male                   | 男性の氏名(漢字)     | 藤本 陽一     |
| last_name_male              | 男性の苗字(漢字)？   | 西之園        |
| first_name_male             | 男性の名前(漢字)     | 淳            |
| last_name_female            | 女性の苗字(漢字)？   | 吉田          |
| first_name_female           | 女性の名前(漢字)     | 知実          |
| romanized_name              | 氏名(ローマ字)       | Akira Sasada  |
| last_romanized_name         | 苗字(ローマ字)       | Ogaki         |
| first_romanized_name        | 名前(ローマ字)       | Naoki         |
| first_romanized_name_male   | 男性の名前(ローマ字) | Manabu        |
| first_romanized_name_female | 女性の名前(ローマ字) | Rei           |
| kana_name                   | 氏名(カナ)           | タカハシ ミキ |
| last_kana_name              | 苗字(カナ)           | サイトウ      |
| first_kana_name             | 名前(カナ)           | ヨウイチ      |
| first_kana_name_male        | 男性の名前(カナ)     | ナオト        |
| first_kana_name_female      | 女性の名前(カナ)     | マイ          |

※苗字に男女の区別があるのかは疑問ですが。。。

# 項目長を調べる
RDBに突っ込むために生成されるデータの項目長を調べました。
[Colaboratory](https://colab.research.google.com/)で確認しました。

```python
# !pip install faker                         # 初回のみ実行
import numpy as np
import pandas as pd
from faker.factory import Factory
Faker = Factory.create
fake = Faker()
fake = Faker("ja_JP")
test_data = []
x = 1000000                              # 計測する回数

%timeit 
for i in range(0, x):
    test_data.append(len(fake.address()))  # 計測したい項目を指定する(fake.xxxxx())

a=np.mean(test_data)
b=np.max(test_data)
print('mean={}、max={}'.format(a,b))
```
100万件で最大50数文字くらいです。

```python
mean=26.205511、max=53
```
何回か試してみましたが、55が最大だったので64文字くらいに考えれば良さそうです。
**Byte数ではないので注意が必要です。**


# Insert用のSQLを生成する(TODO)
宿題ですが、必要な項目を指定したら、RDBにテーブルを作成できるように「CREATE TABLE」文と、「INSERT」文を生成するWRAPPERを作りたいな、と思っています。
~~* Fakerが各メソッド毎に吐き出す項目名の桁数と属性を調べる必要があります。~~
* RDB毎の方言をどこまで吸収できるか調査が必要です。First TargetはMySQLになると思います。
* 簡易に項目を選択できるような標準パターンをいくつか考えなければいけません。

---
取り敢えず、今日のところはこの辺で勘弁しといたろ。