고객 데이터 다루기 · 없음과 같음 · 이론
없음은 한 가지가 아니고, 같음도 한 가지가 아니다
한 줄 요약
같은 파일 안에서 "없음" 은 다섯 가지 모양으로 적혀 오고, "같다" 는 세 가지 뜻으로 쓰인다. 둘 다 표기가 아니라 규칙으로 다뤄야 숫자가 흔들리지 않는다.
왜 이게 필요했나
고객 명부를 받아 평균 구매액을 냈다. 57,500원이 나왔다. 고객사에서는 46,000원이라고 한다. 같은 파일을 보고 있는데 답이 다르다.
원인은 대개 한 곳이다. 금액 칸에 값이 없는 행을 한쪽은 빼고 셌고, 다른 쪽은 0 으로 채워서 셌다. 그런데 더 곤란한 것은, 어느 쪽도 자기가 그렇게 하고 있다는 것을 모른다는 점이다. 스프레드시트의 평균 함수는 빈 칸을 빼고, 파이썬으로 짠 코드는 흔히 float(x or 0) 으로 0 을 채운다. 둘 다 오류를 내지 않는다.
여기에 표기 문제가 겹친다. 한 파일 안에서 없음이 빈 칸, NULL, NA, -, 0, 그리고 9999-12-31 같은 보초 날짜로 섞여 온다. 시스템이 셋이면 표기도 셋이고, 합칠 때 아무도 통일하지 않았기 때문이다.
어떻게 동작하나
첫 번째 일은 세는 것이다. 고치기 전에 표기별로 몇 건인지를 먼저 내야 한다. 그 표가 없으면 어떤 처리를 해도 그 처리가 옳았는지 판정할 수 없다.
두 번째는 0 과 없음을 가르는 것이다. 이 둘은 다른 사실이다. 구매액이 0 원인 고객은 "가입은 했는데 아직 안 샀다" 이고, 구매액이 비어 있는 고객은 "얼마인지 모른다" 이다. 평균을 낼 때 전자는 분모에 들어가야 하고 후자는 빠져야 한다. 그런데 파일에 0 이라고 적혀 있으면 둘 중 어느 쪽인지 파일만 봐서는 알 수 없다. 그래서 0 의 건수를 따로 세어 보고하고, 어느 쪽인지는 업무에 물어본다.
같은 400행, 같은 금액 칸 결측을 0 으로 채운 평균 46,000원 분모 400 결측을 뺀 평균 57,500원 분모 320 0 까지 뺀 평균 61,333원 분모 300세 숫자가 다 맞다. 다른 것은 무엇을 세었는가이고, 그것을 말하지 않은 보고서는 틀린 보고서다.
세 번째가 보초값이다. 9999-12-31 은 "아직 안 끝났다" 를 날짜 칸에 억지로 넣은 표기다. 이것을 날짜로 받아들여 처리 기간을 평균 내면 수천 년이 나온다. 우스워 보이지만, 실제로는 이런 값이 몇 건만 섞여도 평균이 조용히 부풀 뿐 눈에 띄지 않는다.
현장에서 만나는 모습
다음은 중복이다. "같다" 는 세 가지 뜻이 있다.
| 종류 | 무엇인가 | 어떻게 다뤄야 하나 |
| --- | --- | --- |
| 완전 중복 | 글자 하나까지 같은 줄이 두 번 | 하나만 남긴다. 판단할 것이 없다 |
| 키 중복 | 같은 식별자인데 내용이 다르다 | 자동으로 못 고친다. 어느 쪽이 맞는지 업무에 묻는다 |
| 사람 눈에만 같은 것 | 표기만 다른 같은 대상 | 정규화하고 규칙을 세워 판정한다 |
세 번째가 어렵다. 문샵, (주)문샵, 문샵 주식회사 는 사람에게는 하나지만 기계에게는 셋이다. 그래서 비교 전에 정규화한다 — 앞뒤 공백을 없애고, 법인 표기를 걷어 내고, 대소문자를 맞추고, 전화번호에서 숫자만 남긴다.
여기서 가장 흔한 사고가 난다. 정규화는 비교를 위한 것이지 병합의 근거가 아니다. 이름을 정규화했더니 두 값이 같아졌다고 해서 같은 회사인 것은 아니다. 지점이 다를 수도 있고, 상호가 우연히 같을 수도 있다. 그래서 판정 규칙은 여러 칸을 함께 본다 — 예를 들어 "정규화한 이메일이 같으면 같은 사람" 이거나 "이름과 전화번호가 둘 다 같으면 같은 사람" 이다.
그리고 결측이 든 칸은 판정 키로 쓸 수 없다. 이메일이 비어 있는 행끼리 "이메일이 같다" 로 묶으면 서로 다른 고객 수십 명이 한 사람이 된다. 이 사고는 조용하고, 결과만 보면 중복 제거가 아주 잘된 것처럼 보인다.
마지막은 블로킹이다. 1만 행을 전부 짝지어 견주면 약 5천만 쌍이다. 그래서 먼저 값싼 키로 행을 나누고 같은 블록 안에서만 견준다. 전화번호 뒤 네 자리 같은 것이 블록 키가 된다. 블로킹은 공짜가 아니다 — 블록이 다르면 영원히 못 만난다. 그래서 블록 키를 고르고 나면 "이 키가 놓치는 쌍이 몇 개인가" 를 작은 표본에서 전수 비교로 재어 보고, 그 손실을 문서에 적는다.
실무에서 진짜 중요한 것
- 고치기 전에 센다. 표기별 건수 표가 모든 판단의 근거다.
- 평균을 말할 때 분모를 함께 말한다. 숫자 하나만 적힌 보고서는 반드시 다시 물어보게 된다.
- 0 과 없음은 다른 사실이다. 파일만 봐서 모르면 업무에 묻고, 답을 문서에 적는다.
- 정규화는 비교용, 판정은 규칙으로. 그리고 결측이 든 칸은 키로 쓰지 않는다.
- 블로킹의 손실을 재어 둔다. 못 만난 쌍은 조용하다.
다음 실습에서 할 것
세 시스템에서 합쳐 온 고객 명부를 직접 만들어, 없음의 표기를 종류별로 세고, 결측을 0 으로 채운 평균과 빼고 낸 평균과 0 까지 뺀 평균 셋을 나란히 낸다. 보초 날짜가 평균 처리 기간을 어떻게 망가뜨리는지도 숫자로 본다. 그다음 완전 중복과 키 중복을 가르고, 정규화와 블로킹으로 견줄 후보를 줄이고, 판정 규칙으로 같은 사람을 묶는다. 마지막에는 블로킹이 놓친 쌍을 전수 비교로 재어 그 손실까지 보고한다. 채점기는 매번 다른 명부를 만들어 여러분의 도구를 실제로 실행하고 답을 대조한다.