清洗是非常重要的,不管是對豬、蘿蔔,還是資料。
先別說客人喝蘿蔔排骨湯的時候咬到泥土,下湯時泥土就會把整鍋湯給毀了!所以清洗是處理食材絕對不可省略的步驟。資料也是一樣,舉例性別資料……小馬對多元性別表達尊重,但為舉例方便,也為避免模糊焦點,暫時我們當作只有男、女兩種性別。
真實故事,我曾經看過某間公司的性別資料,裡面包括:男、女、男生、女生、男性、女性、男姓(打錯字)、F、f、M、m、Female、Male、female(各種單字縮寫和大小寫不同)……,這些就算了,我像盛竹如一樣繼續看下去,於是看到093xxxxxxx的手機資料、還有屏東縣xxx的地址資料……裡面何止有兩種?根本有上百種!
你可以想像性別圓餅圖跑出來,不是一分為二的乾淨俐落,而是如上切分了n種色塊嗎?
因此,這勢必要處理的。
首先決定好最終想要看到什麼,是想要看到【男、女】,還是想要看到【男性、女性】、還是【M、F】?假設我決定最終要設計成【男、女】,接著,就必須開始做收斂歸類,透過寫程式、寫公式、寫SQL……總之透過某些作業,將男生、男性、男姓、M、m、Male、male等等全數歸類成「男」,「女」的歸類同理就不再贅述。
最後,將無法分辨男女的例如手機資料、地址資料,列為null,強烈建議是null,再差也至少要是空白,而不是半形空格、全形空格、未填寫、其他等等。
--未能歸類的拜託用null或空白
ELSE null END --首選Null
ELSE '' END --至少也得是空白
--拜託不要啊!
ELSE ' ' END --半形空格
ELSE ' ' END --他馬兒的全形空格
ELSE ' ' END --tab?
--你知道上面這幾種它馬兒的光看資料根本分不出來,一跑結果有各種看起來一樣的東西。
'其他' --好吧
'未填寫' --我知道你AP端設計這樣,但你寫資料可不可以不要寫這三個字啊?
'沒寫' --真口語,謝謝喔~
'none' --要不乾脆寫nobody but you?
真正清洗完的性別資料,只會有三種內容:男、女、null(不存在/空集合)。
本篇並非在教導人如何做資料清洗,而是將這些名詞清楚定義和歸類,故這邊只會很簡單的提到舉例的處理方式,不會廣泛的提及資料清洗會遇到的狀況,或更深入的資料清洗(例如地址正規化)怎麼做。不過有時看寫文章的時間,偶爾會有些【番外篇】,幹譙一下...呃不是...聊一下過去遇到的一些狀況和事後體悟。不過番外畢竟不是本系列文重點,有些行內話就不多花時間解釋了。
看過很多文章,會將【資料清洗(Data Cleansing)】說成是【資料採礦(Data Mining)】,就很寬鬆的定義來看可能還說得通,但容小馬重述初衷:致力將這些專有名詞定義在最恰當的位置。明天,小馬將清楚定義【B-3.資料採礦(Data Mining)】。
B-2.資料清洗(Data Cleansing):
清洗完整食材,將食材分為可吃及不可吃,將可吃的保留、不可吃的清洗掉或去除。
處理原始資料,決定心目中應該呈現的資料長相,將資料分為可用及不可用(不可辨識/雜亂資料/骯髒資料),將可用的收斂歸戶歸類,將不可用的歸納成同一類。
資料輸入端如果可以防呆,處理資料的人當然樂見。
但當這發生在一個具規模的大公司裡,當處理資料的人發現這事反映回去給AP端時,改不改是一回事(有時還牽涉部門權責和政治問題),改版過程和壓力測試,所帶來的風險和排擠其他案子的效應,通常會讓大家不敢動作。因此上頭決策下來,都是請處理資料的部門吃下來,反正你們可以處理啊,只是多寫幾條CASE WHEN而已不是嗎?
小馬初入行時對這種現象還很感冒,但隨著年紀增長,會覺得從大局評估,由資料處理端去SQL解決掉,確實風險最低,就是麻煩了點,但反正公司養我們在這,就是做這些事情的嘛,當作工作本份吧。再退幾步來看,這些雜亂資料,縱使AP端克服萬難改完了,這些歷史資料難道你不用嗎?你還是得用啊!你那幾條CASE WHEN還是得寫啊,想到最後,就連反映給AP端都懶了。
當已經到了資料處理端,明明是同一件事,卻還用不同的代詞去做的時候,就會讓人很著惱了。
Null的好處在於寫over partition時,你可以很自如的用Max或Min去找到你真正想要的值,但如果這時候不是Null,而是空格或空白這種亂七八糟,很多時候下完MIN,跑出來的就是這些亂七八糟。
舉個例子,你將會員分成A~E群,你想要知道這五群裡面,在限定的資料區間內,各自最早一次交易的人是誰是什麼時候,並當作這個群的基準點,以利後續運算同群的其他人的量化值。
MIN(trans_daytime) over (Partition by "groupA~E")
你預期的是跑出5個人和他們的各自日期時間,不過因為資料區間關係,某些人沒有【最早一次交易】的值。如果壓上的是null,那跑出來的就會是有值且最早的人(正解);但如果壓上的是那些亂七八糟,跑出來的就是沒值被壓上亂七八糟的人(歪解)。這是null的好處之一。
你有沒有看過一個select,必須trim整排欄位的狀況?
select
TRIM("colA"),
TRIM("colB"),
TRIM("colC"),
...
TRIM("colZ")
from ...
--小馬每天都看到
不trim後面會很麻煩,為什麼會有這現象?因為資料庫通常是代代相傳,很多時候,明明欄位A已經記錄了性別,但可能AP端改過或是人員忘記...whatever...,然後欄位B又記了一次性別,甚至會遇到,一個會員,你必須找5個欄位才能確認他有沒有寫性別。
突然某天靈光一閃,這人員彷彿想起平行世界的記憶,對啦!之前有用到欄位A!那這樣吧,寫個...
欄位A||欄位B as 性別
於是資料就會變成這樣
' 男'
'男 '
' '
因為之前沒資料的地方他塞了空格進去!你可以試著想像一下如果現在是把三四個欄位組在一起的時候,一個單純的【男】字,會有幾種排列組合?
欸好了,時間差不多了,今日的murmur番外篇就先到這。
明天我們還是以名詞說明為主,番外篇比較有趣我知道(自以為XD),但畢竟不是參賽初衷,所以囉~