TT Lab
はじめる
学ぶ 学習パス コース

顧客データを扱う

13週目に売上がゼロになった — 受信契約をコードにする

TT Labで続きを見る

目標

毎週届くファイルからスキーマを取り出してフィンガープリントとして固め、カラムの追加・削除・名前の変更・型の変更を分類して、互換性ルールで自動判定するツールschema.pyを作ります。最後に、名前も型もそのままで意味だけが変わったカラムを、値の分布で検出します。

なぜ重要なのか

他人が渡すファイルのスキーマは、通知なしに変わります。送る側は自分のシステムのフィールドを整理しただけで、受け取る側はそれを契約として使っていただけです。私たちは変える側を管理できないので、できることは、変わったという事実をパイプラインが先に察知できるようにすることだけです。 察知したあとのほうが、さらに重要です。知らないカラムが1つ増えたせいでロードを止めれば、誰もその警告を信頼しなくなり、必須カラムが消えたのにそのまま通せば、数字が静かに間違います。そのため、何が壊れて何が壊れないかを、ルールとして明文化しておきます。基本は2行です。知らないカラムは通し、なくなった必須カラムは中断します。 そして、スキーマ検査が絶対に見られないものが1つあります。金額の単位がウォンから千ウォンに変わると、カラム名も型もそのままです。検査はすべて通過し、売上だけが1000分の1になります。こうした変化は値の分布でしか見えず、分布は証拠ではなく手がかりです。 採点ツールは、提出された文言を信じません。一時ディレクトリに、採点ツールが作った週次のファイルを用意し、作成したツールを実際に実行して、分類と判定を照合します。社名と金額は、実行ごとに変わります。

ステップ

  1. /root/drift/gen_weeks.pyを作成して実行し、weeksディレクトリの下にw01.csvからw07.csvまでを作成してください(保存先: /root/drift/weeks)。注文30件はずっと同じで、スキーマだけが変わります。
  2. /root/drift/schema.pyにfingerprintを作成して、カラム名・型・値サンプルとフィンガープリントを出力させ、w01.csvのフィンガープリントを保存してください(保存先: /root/drift/baseline.json)。
  3. diff <기준 JSON> <파일>を追加して(プレースホルダーは基準JSONとファイルです)、カラムの追加と削除を分類させてください。
  4. diffが、値サンプルが大きく重なる組を探して、名前の変更として分類するようにしてください。名前の変更として検出されたカラムは、追加・削除の一覧から外れます。
  5. diffが、同じカラムの型の変更を分類するようにしてください。名前が変わると同時に型も変わった場合まで見ます。
  6. /root/drift/contract.jsonに必須・任意のカラムとルールを宣言し、gate <기준 JSON> <파일>がpass・warn・stopを判定するようにしてください(プレースホルダーは基準JSONとファイルです)。
  7. watch <기준 CSV> <파일>を追加して(プレースホルダーは基準CSVとファイルです)、数値カラムの中央値の変化を測らせ、単位が変わった週を書いてください(保存先: /root/drift/meaning.json)。
  8. 7週間分を一度に判定して、/root/drift/drift_report.jsonと、/root/drift/drift_report.mdを作成してください。

参考

7週間分の受信ファイルを作る

/root/drift/gen_weeks.pyを作成して実行し、weeksディレクトリの下にw01.csvからw07.csvまでを作成してください(保存先: /root/drift/weeks)。注文30件はずっと同じで、カラムだけが週ごとに変わります。

基準の週の行を辞書のリストとして作っておき、週ごとにカラムのリストと値だけを手直しして、書き直せば足ります。値がずっと同じでなければ、あとで値サンプルから名前の変更を見つけられません。単位が変わる週だけ、値を直します。

スキーマをフィンガープリントとして固める

/root/drift/schema.pyにfingerprint <파일>を作成し(プレースホルダーはファイルです)、rows・columns・digestを出力させ、w01.csvのフィンガープリントを保存してください(保存先: /root/drift/baseline.json)。

カラムごとに値を集めて型を推論し、異なる値を並べ替えて、先頭20個をサンプルとして入れます。フィンガープリントは、名前と型だけをつなげてハッシュします。サンプルまで入れると、データが変わるたびにフィンガープリントが変わって、役に立たなくなります。

増えたカラムとなくなったカラムを分ける

diff <기준 JSON> <파일>を追加して(プレースホルダーは基準JSONとファイルです)、added・removed・renamed・retypedの4つの一覧を出力させてください。このステップでは、追加と削除だけを埋めてもかまいません。

基準のフィンガープリントと新しいファイルのフィンガープリントから名前の集合を取り出して、差集合を求めれば、追加と削除が出ます。一覧は並べ替えて出力してください。順序が実行ごとに変わると、比較できません。

名前だけが変わったカラムを突き止める

diffが、消えたカラムと増えたカラムの値サンプルのジャッカード類似度が0.8以上なら、名前の変更として分類するようにしてください。名前の変更として検出されたカラムは、addedとremovedから外れます。

名前だけを見れば、消えたもの1つと増えたもの1つです。値を見れば、同じカラムです。消えたカラムごとに、増えたカラムとのサンプル集合の積集合の大きさを和集合の大きさで割り、最も高い組を選んで、しきい値を超えたときだけ名前の変更とみなします。

型が変わったカラムを見分ける

diffが、同じ名前のカラムの型の変更を、retypedに[이름, 옛타입, 새타입]として入れるようにしてください(プレースホルダーは順に、名前、旧型、新型です)。名前が変わると同時に型も変わった場合は、新しい名前で入れます。

型は推論した値なので、資料が少し変わるだけで変わることがあります。そのため、整数が小数の表記に変わったものと、数字が文字列になったものを区別できるように、旧型と新型を一緒に入れておいてください。次のステップで、この2つを別の等級として扱います。

互換性ルールをコードで明文化する

/root/drift/contract.jsonにrequired・optional・rulesを宣言し、gate <기준 JSON> <파일>が{"verdict": …, "reasons": [...]}を出力するようにしてください(プレースホルダーは基準JSONとファイルです)。知らないカラムは通過、なくなった必須カラムはstopです。

必須カラムの一覧は、業務が決めるものです。order_id・shop_id・qty・amount_krw・ordered_atがなければ集計を作れず、shop_nameとweightはなくても集計は出ます。reasonsは並べ替えて出力し、理由ごとに、どのカラムが原因かの名前を付けてください。

スキーマが見られない変化を検出する

watch <기준 CSV> <파일>を追加し(プレースホルダーは基準CSVとファイルです)、2つのファイルの両方にある数値カラムの中央値と比率を測らせてください。そして、単位が変わった週を、column・median_before・median_after・ratio・flag・schema_verdictとして書いてください(保存先: /root/drift/meaning.json)。

この変化は、カラム名も型もそのままなので、前のステップの判定がすべて通過します。値の分布だけが落ち込みます。比率が3以上、または3分の1以下なら、人が見る必要があるという印を付けてください。証拠ではなく手がかりです。schema_verdictには、同じ週に対するgateの判定を一緒に書き、スキーマ検査がこれを見られないという事実を残してください。

7週間分を1枚で報告する

7週間分を基準の週と照合して、baseline・weeks・pass・warn・stopを書き(保存先: /root/drift/drift_report.json)、/root/drift/drift_report.mdに、## 무엇이 바뀌었나、## 무엇이 깨지고 무엇이 안 깨지나、## 자동으로 잡히지 않는 것、## 보내는 쪽과 맞출 것の4つの節で書いてください(韓国語の見出しは順に「何が変わったか」「何が壊れ、何が壊れないか」「自動では検出できないもの」「送る側と合わせること」という意味です)。

weeksは、ファイル名をキーにして、verdict・added・removed・renamed・retypedを入れたオブジェクトです。基準の週自身も入れると、判定がpassになって、照合しやすくなります。レポートには、stopになった週とその理由を、数字とともに書いてください。