從官方例子入手 (詳解資料清洗)——kettle實戰(5)
注:本篇文章參考《Pentaho Kettle解決方案:使用PDI構建開源ETL解決方案》
資料清洗步驟
Kettle 裡沒有單一的資料清洗步驟,但又很多的步驟組合起來可以完成資料清洗的功能。(也可以使用”表輸入”步驟裡的可自定義的sql語句來做一些清洗工作,只抽取出必要的資料再傳遞給後面的步驟。但要注意,SQL 語句太複雜會使以後的維護工作比困難。當然我們也可以把資料原樣讀出來然後使用 Kettle 步驟轉換,這裡需要使用者在效率和維護性之間平衡。)
下面舉了兩個例子
利用“Calculator(計算器)進行資料清洗工作相關的選項”
ISO8601星期和年份數字:美國以外的很多國家使用不同的基於ISO8601標準的星期數字。不是所有的資料庫都能從日期型別獲得正確的星期和年份資料,所以計算器步驟裡的這個功能很有用
大小寫轉換:首字母大寫,全部大寫,全部小寫可以讓字串的大小寫統一。
返回/移除數字:這個功能可以把既包含數字也包含字母的字串拆分成數字和字母部分。例如,荷蘭的郵政編碼就是這樣的字串,它包含四位數字和兩位字母(如1234AB)
由於實踐過後發現此步驟難度不是很大,所以在此不浪費篇幅來描述它。
“Replace in string(字串替換)”步驟
下面的轉換來自於官方的例子:
(…\data-integration\samples\transformations\Replace in string - Simple example.ktr)
Generate Rows:
下面是步驟內容和預覽資料,也就是說這兩個欄位分別生成一百萬條。
下面才是重點
Replace in string:
我們先看一下最後替換後的結果然後對比來看
(最後這個dummy步驟稍後說到官方例子時會給出具體說明)
這裡我們一目瞭然:輸入流欄位也就是想要被替換的欄位名字,輸出流欄位就是替換後的新的欄位名字,是否使用正則表示式是這個步驟中特別強大的功能,相比後面的功能比如單純地使用“搜尋”欄位,“使用…替換”,正則更靈活更強大。設定為空串就是如果搜尋到了相應欄位那麼設定為空
另外x1和x2都比較簡單,唯一需要注意的就是x3,是在欄位中每個字元的前後都加上那個字元,不過感覺這個用法不是很常用。=。=
“Fuzzy match(模糊匹配)”步驟
注:此步驟在“轉換”的“查詢”中
在此之前我們先了解一下
Kettle裡的字串匹配演算法:
kettle裡有兩個地方能找到相似度演算法:“Calculator”步驟和“Fuzzy match”步驟偶這兩個步驟裡的相似度演算法幾乎一樣,但是工作方式不一樣;“Calculator”步驟比較一行裡的兩個欄位,而“Fuzzy match ”步驟使用查詢的方式,從字典表中查詢出相似度在一定範圍內的記錄。我們在使用這些步驟和演算法之前,最好能理解這些演算法的概念和用途。開啟“Fuzzy match”步驟,選中演算法列表,可以看到有很多可用的演算法,如“Damerau-Levenshtein”,”Jaro Winkler”,”Double Metaphone”。這些演算法的共同點就是用來做字串匹配。但是他們的工作方式不一樣,所以不同演算法適合做不同的工作,如排重之類的工作。下面解釋一下這些演算法。
Levenshtein和Damerau-Levenshtein:編輯一個字串到另一個字串需要多少步驟,根據步驟數,來計算兩個字串之間的距離。第一個演算法裡的編輯步驟只包括插入字元,刪除字元,更新字元,第二個演算法裡還包括調換字元位置的步驟。需要的最少步驟數就是最後的結果,例如”CASTERS”和“CASTRO”這兩個字串的距離就是2(步驟1:刪除字母E;步驟2:把字母S替換成O)
Needleman-Wunsch: 這個演算法主要用於生物資訊學領域,以差異扣分的方法來計算距離,上面的CASTERS和CASTRO的距離是-2
Jaro和Jaro-Winkler: 計算兩個字串的相似度,結果是介於0(完全不一樣)到1(完全一樣)之間的小數。例如我們使用Lenvenshtein演算法計算CASTERS和POOH相似度時,結果是7,而使用Jaro或Jaro-Winkler演算法時,結果是0,因為兩個字串之間沒有任何相似度。而Levenshtein演算法總會得到一個距離,因為一個字串經過編輯總是可以變成另一個字串。
Pair Letters similarity: 只有“Fuzzy match”步驟裡有這個演算法,這個演算法把兩個字串都分割成多個字元對,然後比較這些字元對。如CASTERS和CASTRO這個例子,這兩個字串被分割成{CA, AS, ST, TE, ER, RS}和{CS,AS,ST,TR,RO},最後的相似度=(相等的字元對個數)乘以2/兩個字串的字元對總個數,這個例子就是(3*2)/11=0.545(這個結果是匹配度非常高的)
Metaphone,Double Metaphone, Soundex和RefinedSoundEx:這些演算法都是利用單詞的發音來做匹配,也稱為語音演算法。這些語音演算法的缺點是以英語為基礎,所以基本不能用於法語,西班牙語,荷蘭語等其他語種。
當然,最後的問題就是我們應該選擇哪個演算法,這取決你要解決的問題。對資訊提取類的需求,例如,提取亞馬遜上所有的圖書,找出和Pentaho相關的圖書,並給出相似度分數,這時就可以使用字元對的模糊匹配演算法。如果要做資料排重工作,而且還可能有拼寫錯誤,這時就要使用Jaro-Winkler演算法。但使用該演算法時要小心匹配不準確的情況,如“Jos van Dongen”和“Davidson”這兩個人名的相似度是0.615,而“Jos van Dongen”和“Dongen, jos van”這兩個人名的相似度是0.604,從計算結果看前面一對人名相似度更高,但是我們可以看出後面的一對人名實際上是同一個人
下面的轉換來自於官方的例子:
(…\data-integration\samples\transformations\Fuzzy match.ktr)中
最終結果:
經過對比我們發現在模糊匹配的步驟中接受了兩個欄位流,Main Row和Ref Data ,那麼究竟哪個是主欄位流哪個是“欄位庫”流呢,我們看模糊匹配的“一般選項”中,有個“匹配流(源)”,這個就是我們所謂的“欄位庫”流(個人覺得這樣理解起來比較容易),那麼下面的“主要流欄位”就是待匹配欄位了。還有需要設定一下用來接收匹配結果的“欄位”選項卡中:“匹配欄位”和“值欄位”,下面那條感覺可寫可不寫,想不到有什麼特別需要的地方=。=,如果大家有的話請在下面評論提醒我,我們一起討論。
至此我們又搞定了一個步驟
“Stream lookup(流查詢)”步驟——使用參照表
在很多場合下,如更正地址資訊等,需要訪問外部的主資料或參照資料(或字典表)。基礎資料淚的應用一般都使用這些資料,如顯示出標準的國家名和州名。但很多其他類的應用,資料並不規範。
(前段日子的文章中提到我們公司要做資料遷移使用參照表時用的是java指令碼的hashmap來進行匹配,過程非常繁瑣,但是用下面的步驟就可以很輕鬆的解決了。)
經過對比發現書中樣例和官方例子都各有不足,但是為了解讀方便我們還是先來看下一書中的樣例:
此部分在書中的樣例的路徑檔案為:
…635179_downloads\635179_code_ch07\ch7files\LookupPostalCode.ktr
解釋一下,注意“流裡的值查詢” look up step 這裡填寫的就是字典步驟,“欄位”就是源欄位(源程式中的PC4應該改為pc4,實際上這本書中的錯誤很多很多),相當於字典中的key。“查詢欄位”就是字典欄位,也相當於字典中的key,(當然這裡容易讓人產生誤解,沒有官方例子那麼眼睛。)也就是說這兩個步驟裡的欄位是通過這個選項來連線到一起的。
指定用來接收的欄位就是我們要告訴程式 哪些欄位是我們要提出來的 ,也就是說要明確指定出來字典中的value到底是哪個欄位。
然後我們看一下官方例子:
…\data-integration\samples\transformations\Stream lookup - basics.ktr
上圖流裡的值查詢視窗最下方是定義了用來接收結果的欄位名字,這個和上個轉換不同的地方就在於它需要滿足兩個條件才會轉。
那麼現在經過仔細比對後,就算你前面有疑問,現在也應該都理解了