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

顧客データを扱う

検証器は緑なのに数字がおかしい

TT Labで続きを見る

目標

カラムごとのプロファイルと、納品の間の分布の変化、そして最初の桁の数字の分布で、形式は合っているのに値が変な資料を見つけ出すツールprofile.pyを作ります。ベンフォードが通用しないカラムを反例として入れて、これが証拠ではなく手がかりであることを、コードが自分で言うようにします。

なぜ重要なのか

スキーマも合っていて欠損もルールどおりなのに、数字が変なことがあります。このとき、「変です」だけでは誰も動きません。根拠が必要で、その根拠は値1つではなく分布です。 プロファイル1つだけでは判断が難しいです。異常は絶対的な値ではなく、前回の納品との差として表れるからです。そのため、プロファイルは納品ごとに残して比べ、しきい値をコードに書いておきます。書いていないしきい値は、次の人が直せません。 最初の桁の数字の分布は、安上がりでよく効くシグナルですが、最も誤解されるシグナルでもあります。分布がずれたというのは、人が見る必要があるという意味であって、誰かが改ざんしたという意味ではなく、値の範囲が狭いカラムでは、正直な資料もいつもずれます。そのため、適用できるかどうかを先に判定する必要があります。 採点ツールは、提出された文言を信じません。一時ディレクトリに、採点ツールが作った納品を用意し、作成したツールを実際に実行して、プロファイルと判定を、採点ツールが自分で計算した値と照合します。取引先と金額は、実行ごとに変わります。

ステップ

  1. /root/prof/gen_feed.pyを作成して実行し、feedディレクトリの下に2026-04.csv・2026-05.csv・2026-06.csvを作成してください(保存先: /root/prof/feed)。3つとも、形式の検証は通ります。
  2. /root/prof/profile.pyにprofile <파일>を作成し(プレースホルダーはファイルです)、カラムごとに型・欠損・ユニーク率・値の長さ・最頻値・範囲を出力させてください。
  3. digits <파일> <칼럼>を追加して(プレースホルダーはファイルとカラムです)、値の長さの分布と、最頻の長さから外れた値を出力させてください。
  4. drift <파일A> <파일B>を追加して(プレースホルダーは2つのファイルです)、納品の間の分布の変化を、しきい値で判定させてください。
  5. benford <파일> <칼럼>を追加して(プレースホルダーはファイルとカラムです)、最初の桁の数字の分布と期待される分布の差を出力させ、2つの納品を比較して書いてください(保存先: /root/prof/benford.json)。
  6. benfordに適用できるかどうかの判定を加えて、値の範囲が狭いカラムには、applicableをfalseに、verdictをnot_applicableにしてください。結果を書いてください(保存先: /root/prof/narrow.json)。
  7. 複数のシグナルを重ねて調査対象の一覧を作り、カラムごとに次に確認することを書いてください(保存先: /root/prof/leads.json)。
  8. 全体を1枚にまとめて、/root/prof/prof_report.jsonと、/root/prof/prof_report.mdを作成してください。

参考

3か月分の納品を作る

/root/prof/gen_feed.pyを作成して実行し、feedディレクトリの下に2026-04.csv・2026-05.csv・2026-06.csvを作成してください(保存先: /root/prof/feed)。2か月は平凡で、1か月は形式は合っているのに値が変です。

金額は、桁が均等に広がるように作ってください。指数を一様に選んで10のべき乗にすれば、最初の桁の分布が自然になります。手を加えた月には、人が書き込んだような金額をいくつか混ぜ、取引先が空の行と電話番号の桁が違う行も一緒に入れてください。標準ライブラリの乱数の代わりに、固定シードの生成器を使えば、誰が実行しても同じファイルが出ます。

カラムごとに自己紹介させる

/root/prof/profile.pyにprofile <파일>を作成し(プレースホルダーはファイルです)、rowsとcolumnsを出力させてください。カラムごとにtype・nulls・null_rate・distinct・unique_ratio・len_min・len_max・modal_length・topを入れ、数値カラムにはmin・maxを加えます。

割合の分母は全体の行数で、長さとユニークな値は、なしを除いた値だけで数えます。topは件数の降順にし、件数が同じなら値の辞書順で決めないと、実行ごとに同じ答えが出ません。

値の長さから外れたものを取り出して見る

digits <파일> <칼럼>を追加し(プレースホルダーはファイルとカラムです)、lengths・modal_length・outliers・sample_outliersを出力させてください。sample_outliersは、異なる値を並べ替えて先頭の3つです。

形式検査を通る値でも、長さが違えば作った側が変わったということです。外れた値を数個、直接取り出して見れば、原因がたいてい、すぐに見えます。電話番号なら、市外局番が抜けたか、ハイフンが消えたかです。

前回の納品と比べる

drift <파일A> <파일B>を追加し(プレースホルダーは2つのファイルです)、カラムごとに4つの変化を測って、しきい値を超えたものをflagsに入れさせてください。応答には、flagsが1つでもあるカラムの一覧flaggedも入れます。

異常は絶対値ではなく差として表れます。欠損率0.05、ユニーク率0.20、最頻値の占有率0.10、そして最頻の長さが変わったかを見ます。しきい値を定数として切り出しておけば、あとで資料が変わったときに、直す場所が1か所で済みます。

最初の桁の数字の分布を測る

benford <파일> <칼럼>を追加し(プレースホルダーはファイルとカラムです)、observed・expected・max_deviation・deviation_digit・verdictを出力させ、平凡な月と手を加えた月のamountの結果を、normal・suspectとして書いてください(保存先: /root/prof/benford.json)。

期待される割合は、桁dに対してlog10(1 + 1/d)です。最初の桁は、符号と先頭の0と小数点を飛ばして最初に出会う0でない数字で、値が0なら数えません。人が手で作り出した金額は、特定の桁に集中するので、差が大きく開きます。

ベンフォードが通用しないカラム

benfordにspanとapplicableを加えて、件数が200未満、または最大/最小の比が100未満なら、適用できないとみなし、verdictをnot_applicableにしてください。scoreカラムの結果を、column・n・span・applicable・verdict・whyとして書いてください(保存先: /root/prof/narrow.json)。

値が狭い区間にしかないと、最初の桁が数種類に限られて、正直な資料も期待される分布と大きくずれます。適用できるかどうかの判定なしに実行したベンフォードは、問題のない資料を報告し続け、そうなると、誰もその報告を読まなくなります。whyには、なぜ適用できないのかを、1–2文で書いてください。

シグナルを重ねて調査対象を作る

分布の変化とベンフォードの結果を重ねて、leads・not_leads・noteを書いてください(保存先: /root/prof/leads.json)。leadsの各項目は、column・signals・next_checkを入れ、not_leadsには、ベンフォードを適用できないカラムを書きます。

1つだけ引っかかったカラムと、3つ引っかかったカラムは、違うように扱う必要があります。next_checkは、「変だ」ではなく、「次に何を確認する」でなければなりません。手で書いたような金額が、どの担当者に集中しているか、桁が変わった電話番号が、どのシステムから来たかのようなものです。

手がかりを1枚で渡す

baseline・target・rows・flagged・benford・not_applicable・leadsを書き(保存先: /root/prof/prof_report.json)、/root/prof/prof_report.mdに、## 무엇을 봤나、## 지난 전달분과 무엇이 달라졌나、## 첫 자리 숫자가 말해 주는 것、## 무엇을 더 확인해야 하나の4つの節で書いてください(韓国語の見出しは順に「何を見たか」「前回の納品と何が変わったか」「最初の桁の数字が語ること」「さらに何を確認すべきか」という意味です)。

benfordは、amountカラムのcolumn・max_deviation・verdictを入れたオブジェクトです。レポートの3つ目の節には、ベンフォードの結果とともに、それがなぜ証拠ではないのかを必ず書き、4つ目の節には、カラムごとに次に確認することを書いてください。前のステップで残したファイルを読んで、まとめれば足ります。