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

顧客データを扱う

平均が二つある — 「なし」と「同じ」を規則で決める

TT Labで続きを見る

目標

なしの表記を種類別に数え、欠損を0で埋めたときに平均がどう変わるかを数字で示し、完全重複とキー重複と人の目にだけ同じものを分けて、正規化・ブロッキング・判定ルールで同じ人をまとめるツールnulls.pyを作ります。

なぜ重要なのか

同じファイルを見て、平均が2つ出ることはよくあります。片方は値がない行を除いて数え、もう片方は0で埋めて数えたからです。どちらもエラーを出さないので、誰も気づきません。そのため、平均を言うときは分母も一緒に言う必要があり、そのためには、表記ごとの件数を先に数えなければなりません。 0となしは別の事実です。0ウォンの顧客は「まだ買っていない」で、空欄の顧客は「わからない」です。ファイルに0と書かれていると、どちらなのかをファイルだけでは判断できないので、件数を別に数えて報告し、業務に尋ねます。 重複も1種類ではありません。1文字まで同じ行は1つだけ残せば足りますが、同じ識別子で内容が違う行は自動では直せず、表記だけが違う同じ対象は、ルールで判定する必要があります。ここで最もよくある事故は、正規化した値が同じになったからといってマージしてしまうことです。 採点ツールは、提出された文言を信じません。一時ディレクトリに、採点ツールが作った名簿を用意し、作成したツールを実際に実行して、件数・平均・まとめられたグループを、採点ツールが自分で数えた値と照合します。名前と金額は、実行ごとに変わります。

ステップ

  1. /root/miss/gen_customers.pyを作成して実行し、customers.csvを作成してください(保存先: /root/miss/raw/customers.csv)。欠損の表記と、3種類の重複が入っています。
  2. /root/miss/nulls.pyにcensus <파일> <칼럼>を作成し(プレースホルダーはファイルとカラムです)、なしの表記を種類別に数えさせてください。
  3. stats <파일> <칼럼>を追加して(プレースホルダーはファイルとカラムです)、欠損を0で埋めた平均と、除いて出した平均と、0まで除いた平均を並べて出力させ、結果を書いてください(保存先: /root/miss/stats.json)。
  4. aging <파일>を追加して(プレースホルダーはファイルです)、センチネル日付が平均処理期間をどう壊すかを測り、結果を書いてください(保存先: /root/miss/aging.json)。
  5. dupes <파일>を追加して(プレースホルダーはファイルです)、完全重複とキー重複を分けて数えさせてください。
  6. blocks <파일>を追加して(プレースホルダーはファイルです)、正規化したあとに電話番号の下4桁でブロックに分け、比べる候補の組がいくつに減ったかを出力させてください。
  7. match <파일>を追加して(プレースホルダーはファイルです)、判定ルールで同じ人をまとめ、ブロッキングが見逃した組まで測らせてください。ルールは、/root/miss/rules.jsonに書きます。
  8. 全体を一度に処理して、/root/miss/miss_report.jsonと、/root/miss/miss_report.mdを作成してください。

参考

3つのシステムから統合した名簿を作る

/root/miss/gen_customers.pyを作成して実行し、customers.csvを作成してください(保存先: /root/miss/raw/customers.csv)。なしの表記5種類と、完全重複・キー重複・表記だけが違う同じ人が一緒に入ります。

まず人を36人作り、そのうち12人を、社名の表記と電話番号の書式だけを変えて、もう一度入れます。そのあと、前の行をそのままコピーした完全重複と、record_idだけが重なって人は別の行を加えます。金額と終了日には、空欄・NULL・NA・ハイフン・0・センチネル日付を混ぜます。

なしの表記を種類別に数える

/root/miss/nulls.pyにcensus <파일> <칼럼>を作成し(プレースホルダーはファイルとカラムです)、total・blank・tokens・zero・sentinel・presentを出力させてください。0はなしとして数えず、別に数えます。

値の前後の空白だけを取り除いて大文字にそろえ、一覧と比べます。0をなしに入れない理由が、このステップの核心です。本物の0なのか埋めた0なのかはファイルだけを見てもわからないので、数えておいて業務に尋ねるのが正しいです。

0で埋めた平均と除いて出した平均

stats <파일> <칼럼>を追加し(プレースホルダーはファイルとカラムです)、3種類の平均を並べて出力させ、amountカラムに対する結果を保存してください(保存先: /root/miss/stats.json)。

3つの平均の違いは分母です。欠損を0で埋めると、合計はそのままで分母だけが大きくなり、平均が下がります。0まで除いた平均は、分母がさらに小さくなって平均が上がります。3つの数字はすべて正しく、間違っているのは、何を数えたかを言わないレポートです。

9999-12-31が作った数千年

aging <파일>を追加し(プレースホルダーはファイルです)、センチネル日付をそのまま日付として受け入れた平均と、除いて出した平均を一緒に出力させ、結果を保存してください(保存先: /root/miss/aging.json)。

9999-12-31は日付ではなく、「まだ終わっていない」という印です。それを日付として計算すると、平均が数千年になります。滑稽に見えますが、数件が混ざるだけで平均が静かに膨らみ、目立ちません。開始日か終了日がなしなら、計算から除いてunknownとして数えます。

完全重複とキー重複を分ける

dupes <파일>を追加して(プレースホルダーはファイルです)、rows・exact・key_dupes・keysを出力させてください。exactは、同じ行が複数回出てきた超過分で、key_dupesは、record_idが2回以上出てきたキーの個数です。

2種類を分けるのは、処理方針が違うからです。1文字まで同じ行は、判断することなく1つだけ残せば足りますが、同じ識別子で内容が違う行は、どちらが正しいかを機械が知りません。そうしたキーは、一覧として残して業務に渡す必要があります。

正規化してブロッキングで候補を減らす

blocks <파일>を追加して(プレースホルダーはファイルです)、rows・blocks・candidate_pairs・pairs_without_blockingを出力させてください。ブロックのキーは、正規化した電話番号の下4桁で、4桁に満たなければNONEです。

すべてを組み合わせて比べると、行数の2乗に比例して増えます。安いキーで先に分ければ、比べる組が大きく減ります。正規化は比較のためのもので、このステップで何かをまとめるものではありません。まとめる仕事は、次のステップのルールが行います。

同じ人をまとめることと、ブロッキングが見逃した組

match <파일>を追加して(プレースホルダーはファイルです)、rows・clusters・merged・groups・recall_lossを出力させてください。ルールは、/root/miss/rules.jsonに、block_key・normalize・match・not_matchとして書きます。

メールアドレスが空の行どうしを「メールアドレスが同じ」としてまとめると、互いに別の顧客数十人が1人になります。ルールに「空でなく」を必ず入れてください。recall_lossは、総当たりの比較で見つけた組から、ブロックの中で見つけた組を引いた値です。ブロッキングはただではないという事実を、数字で残す場所です。

欠損と重複を1枚で報告する

全体を一度に処理して、rows・missing・mean_naive・mean_known・exact・key_dupes・clusters・merged・recall_lossを書き(保存先: /root/miss/miss_report.json)、/root/miss/miss_report.mdに、## 없음은 몇 가지로 적혀 있었나、## 0 으로 채우면 무엇이 달라지나、## 무엇을 같은 것으로 봤나、## 남은 위험の4つの節で書いてください(韓国語の見出しは順に「なしはいくつの形で書かれていたか」「0で埋めると何が変わるか」「何を同じものとみなしたか」「残るリスク」という意味です)。

missingは、カラム名をキーにして、censusの結果を入れたオブジェクトです。amountとclosed_atの2つのカラムを入れてください。レポートには、3つの平均を分母とともに書き、ブロッキングが見逃した組の数を、残るリスクに書いてください。その組は、誰も報告しません。