LabHub
배우기 러닝패스 코스

顧客データを扱う

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

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

없음의 표기를 종류별로 세고, 결측을 0 으로 채웠을 때 평균이 어떻게 달라지는지를 숫자로 보이고, 완전 중복과 키 중복과 사람 눈에만 같은 것을 갈라 정규화·블로킹·판정 규칙으로 같은 사람을 묶는 도구 nulls.py 를 만든다.

왜 중요한가

같은 파일을 보고도 평균이 두 개 나오는 일은 흔하다. 한쪽은 값이 없는 행을 빼고 셌고 다른 쪽은 0 으로 채워 셌기 때문이다. 둘 다 오류를 내지 않아서 아무도 알아채지 못한다. 그래서 평균을 말할 때는 분모를 함께 말해야 하고, 그러려면 표기별 건수를 먼저 세야 한다. 0 과 없음은 다른 사실이다. 0 원인 고객은 "아직 안 샀다" 이고 빈 칸인 고객은 "모른다" 이다. 파일에 0 이라고 적혀 있으면 둘 중 어느 쪽인지 파일만 봐서는 알 수 없으므로, 건수를 따로 세어 보고하고 업무에 묻는다. 중복도 한 가지가 아니다. 글자까지 같은 줄은 하나만 남기면 되지만, 같은 식별자에 내용이 다른 줄은 자동으로 고칠 수 없고, 표기만 다른 같은 대상은 규칙으로 판정해야 한다. 여기서 가장 흔한 사고는 정규화한 값이 같아졌다는 이유로 병합해 버리는 것이다. 채점기는 여러분의 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 명부를 차려 놓고 여러분의 도구를 실제로 실행해 건수·평균·묶인 그룹을 채점기가 직접 센 값과 대조한다. 이름과 금액은 실행마다 바뀐다.

단계

  1. /root/miss/gen_customers.py 를 만들어 실행해 /root/miss/raw/customers.csv 를 만드세요. 결측 표기와 세 종류의 중복이 들어 있습니다.
  2. /root/miss/nulls.pycensus <파일> <칼럼> 을 만들어 없음의 표기를 종류별로 세게 하세요.
  3. stats <파일> <칼럼> 을 더해 결측을 0 으로 채운 평균과 빼고 낸 평균과 0 까지 뺀 평균을 나란히 내게 하고, 결과를 /root/miss/stats.json 에 적으세요.
  4. aging <파일> 을 더해 보초 날짜가 평균 처리 기간을 어떻게 망가뜨리는지 재고, 결과를 /root/miss/aging.json 에 적으세요.
  5. dupes <파일> 을 더해 완전 중복과 키 중복을 갈라 세게 하세요.
  6. blocks <파일> 을 더해 정규화한 뒤 전화번호 뒤 네 자리로 블록을 나누고, 견줄 후보 쌍이 몇 개로 줄었는지 내게 하세요.
  7. match <파일> 을 더해 판정 규칙으로 같은 사람을 묶고 블로킹이 놓친 쌍까지 재게 하세요. 규칙은 /root/miss/rules.json 에 적습니다.
  8. 전체를 한 번에 처리해 /root/miss/miss_report.json/root/miss/miss_report.md 를 만드세요.

참고

세 시스템에서 합쳐 온 명부 만들기

/root/miss/gen_customers.py 를 만들어 실행해 /root/miss/raw/customers.csv 를 만드세요. 없음의 표기 다섯 가지와 완전 중복·키 중복·표기만 다른 같은 사람이 함께 들어갑니다.

사람 36명을 먼저 만들고, 그중 12명을 상호 표기와 전화번호 서식만 바꿔 다시 넣습니다. 그다음 앞의 줄을 그대로 복사한 완전 중복과, record_id 만 겹치고 사람은 다른 줄을 더합니다. 금액과 종료일에는 빈 칸·NULL·NA·하이픈·0·보초 날짜를 섞습니다.

없음의 표기를 종류별로 세기

/root/miss/nulls.pycensus <파일> <칼럼> 을 만들어 total·blank·tokens·zero·sentinel·present 를 내게 하세요. 0 은 없음으로 세지 않고 따로 셉니다.

값을 앞뒤 공백만 걷어 내고 대문자로 맞춰 목록과 견줍니다. 0 을 없음에 넣지 않는 이유가 이 단계의 핵심입니다 — 진짜 0 인지 채워 넣은 0 인지 파일만 봐서는 알 수 없어서, 세어 두고 업무에 묻는 것이 맞습니다.

0 으로 채운 평균과 빼고 낸 평균

stats <파일> <칼럼> 을 더해 세 가지 평균을 나란히 내게 하고, amount 칼럼에 대한 결과를 /root/miss/stats.json 에 저장하세요.

세 평균의 차이는 분모입니다. 결측을 0 으로 채우면 합계는 그대로인데 분모만 커져 평균이 내려갑니다. 0 까지 뺀 평균은 분모가 더 작아져 평균이 올라갑니다. 세 숫자가 다 맞고, 틀린 것은 무엇을 세었는지 말하지 않는 보고서입니다.

9999-12-31 이 만든 수천 년

aging <파일> 을 더해 보초 날짜를 그대로 날짜로 받아들인 평균과 빼고 낸 평균을 함께 내게 하고, 결과를 /root/miss/aging.json 에 저장하세요.

9999-12-31 은 날짜가 아니라 '아직 안 끝났다' 는 표시입니다. 그것을 날짜로 계산하면 평균이 수천 년이 됩니다. 우스워 보이지만 몇 건만 섞이면 평균이 조용히 부풀 뿐 눈에 띄지 않습니다. 시작일이나 종료일이 없음이면 계산에서 빼고 unknown 으로 셉니다.

완전 중복과 키 중복 가르기

dupes <파일> 을 더해 rows·exact·key_dupes·keys 를 내게 하세요. exact 는 같은 줄이 여러 번 나온 초과분이고, key_dupes 는 record_id 가 두 번 이상 나온 키의 개수입니다.

두 종류를 가르는 이유는 처리 방침이 다르기 때문입니다. 글자까지 같은 줄은 판단할 것 없이 하나만 남기면 되지만, 같은 식별자에 내용이 다른 줄은 어느 쪽이 맞는지 기계가 모릅니다. 그런 키는 목록으로 남겨 업무에 넘겨야 합니다.

정규화하고 블로킹으로 후보 줄이기

blocks <파일> 을 더해 rows·blocks·candidate_pairs·pairs_without_blocking 을 내게 하세요. 블록 키는 정규화한 전화번호의 뒤 네 자리이고, 네 자리가 안 되면 NONE 입니다.

전부 짝지어 견주면 행 수의 제곱에 비례해 늘어납니다. 값싼 키로 먼저 나누면 견줄 쌍이 크게 줄어듭니다. 정규화는 비교를 위한 것이지 이 단계에서 무엇을 합치는 것이 아닙니다 — 합치는 일은 다음 단계의 규칙이 합니다.

같은 사람 묶기와 블로킹이 놓친 쌍

match <파일> 을 더해 rows·clusters·merged·groups·recall_loss 를 내게 하세요. 규칙은 /root/miss/rules.json 에 block_key·normalize·match·not_match 로 적습니다.

이메일이 비어 있는 행끼리 '이메일이 같다' 로 묶으면 서로 다른 고객 수십 명이 한 사람이 됩니다 — 규칙에 '비어 있지 않고' 를 반드시 넣으세요. recall_loss 는 전수 비교로 찾은 짝에서 블록 안에서 찾은 짝을 뺀 값입니다. 블로킹은 공짜가 아니라는 사실을 숫자로 남기는 자리입니다.

결측과 중복을 한 장으로 보고하기

전체를 한 번에 처리해 /root/miss/miss_report.json 에 rows·missing·mean_naive·mean_known·exact·key_dupes·clusters·merged·recall_loss 를 적고, /root/miss/miss_report.md## 없음은 몇 가지로 적혀 있었나 ## 0 으로 채우면 무엇이 달라지나 ## 무엇을 같은 것으로 봤나 ## 남은 위험 네 절로 쓰세요.

missing 은 칼럼 이름을 키로 두고 census 결과를 담은 객체입니다. amount 와 closed_at 두 칼럼을 넣으세요. 보고서에는 평균 세 개를 분모와 함께 적고, 블로킹이 놓친 쌍의 수를 남은 위험에 적으세요 — 그 쌍은 아무도 신고하지 않습니다.