回顧一下:
原文復習(點擊查看): 今天將帶來第9天的學習日記。 目錄如下: 前言 1. 正則表達式簡介 (1)元字符 (2)函數 2. 用正則表達式處理Pandas數據 (1)匹配行 (2)提取匹配文字 (3)提取匹配文字的一部分 統計師的Python日記【第9天:正則表達式】 前言 根據我的Python學習計劃:
在數據清洗的學習過程中,發現文本數據的處理并非一招半式能解決,有時必須要搬出利器——正則表達式。在之前的【SAS正則表達式】系列中(在后臺回復【sasre】查看),我用正則表達式做文本處理做的非常之爽,比如下面這列數據:
這是一份產品名單,有的用數字來編碼,有的直接是產品的名字,現在想把數字編碼(也即紅色字體)的部分提取出來,看似沒有什么規律,但是在SAS中,用正則表達式兩行代碼就搞定了。 現在,要挑戰用正則表達式處理Pandas的數據。 1. 正則表達式簡介 雖然在SAS中學了正則表達式的基礎,Python稍有不同,現在還是簡單復習一下: (1)元字符 元字符是一系列代碼,用來簡化表達某種意思,比如: \d 表示數字 \D 表示非數字 \w 表示單詞字符 \W 表示非單詞字符 等等。 有一個技術博客里給了很好的總結,網址:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html,以備查詢。 (2)函數 在SAS中,PRXPARSE()是獲取一個正則表達式的pattern,在Python中對應的就是 compile() 。
比如說,
那它有什么用呢?pattern后面可以接函數,來實現一些文本處理的功能,比如:
有點抽象,來具體學習一下,以text為例: text='Shu Shuojun, I love u, 520' 這個文本,如果想將它變成一個list,用逗號來分割,我可以這樣: pattern = re.compile(',') pattern.split(text) 結果為: 而利用 findall(),我可以尋找某種格式的字符,相當于SAS中的PRXMATCH(),比如想找到以Sh開頭的字符: pattern = re.compile('Sh\w*') pattern.findall(text) \w表示單詞字符,*表示匹配前面的表達式0次或無限次,\w*也就是匹配一個單詞0次或無限次,'Sh\w*'這個元字符的意思就是:匹配以Sh開頭,后面跟著N個單詞字符的文本(N取0到無窮)。 Sh開頭的兩個單詞都被匹配出來了。 search() 跟findall類似,findall返回的是字符串中所有的匹配項,search則只返回第一個匹配項,的起始位置和結束位置!相當于SAS中的PRXSUBSTR(),同樣以剛才的例子,換成search()看看會發生什么變化: pattern = re.compile('Sh\w*') pattern.search(text) search()返回的是起始位置和結束位置,分別記錄在這個東東的.start()和.end()兩個函數里面,因此要這樣: pattern = re.compile('Sh\w*') m = pattern.search(text) print text [ m.start() : m.end() ] 所以search()只記錄了第一個匹配項的開頭和結束位置。 還有一個函數 match(),與search()不同之處在于,它只匹配字符串的開頭部分: 從這里看與search沒什么差別,因為text的開頭就是Shu,如果換一下只匹配Shushuo看看,也就是pattern改成:pattern = re.compile('Sh\w\w+') 用search()完美匹配出來了,+表示匹配前面的字符至少一次。用match()呢? 不行,匹配不出來,因為Shuojun不是出現在開頭。
sub() 方法是用來替換,SAS中的PRXCHANGES也提供了替換,比如現在想把text中的520換成250: pattern = re.compile('\d+') pattern.sub('250',text) \d表示數字字符,\d+表示匹配數字字符至少1次,由于text中的數字只有520,因此,text中符合pattern的必然是520這部分。 pattern.sub('250',text)就是把text中520換成250: 在SAS中,學過 “打包”, 在Python的正則表達式也可以“打包”,比如將”I love shushuo”中的shu和shuo分別打包: text = 'I love shushuo' pattern = re.compile( '(shu)(shuo)' ) m = pattern.search(text) m.groups() 再比如,將ve和shuo打包: 正則表達式是文本分析的利器,在爬蟲中用處也非常大。但本文中,我要挑戰的是對DataFrame結構數據進行正則表達式的處理。參照SAS正則表達的介紹,試圖將在SAS中實現的功能在Python中也能實現。 2. 用正則表達式處理Pandas數據 (1)匹配行 我在SAS中用正則表達式解決的第一個問題是是這樣的:
也就是開頭的問題,這一份產品列表,現在只想要數字編碼、也就是紅色字體的部分。如何操作? 先來分析一下:
首先兩個PD不是必須的,有的有、有的沒有,但后面(XX)括號里面兩個數字是必須的,我就按照這樣的模式來獲取紅色字體部分:
pattern = re.compile('P?D?\D\d{2}\D\s?\d{4}-\d{4}')
這個表達式如何匹配的?
對于單個字符串很簡單,findall一下就可以了,正如第一部分的介紹,但是對于DataFrane的數據結構,該如何實現? 先讀入Pandas中去,數據就命名為production: 我搗鼓出了兩種方法: 方法一:
成功匹配出來了。 方法二: 思路是將匹配行的索引記錄下來,而不是觀測值:
也可以成功匹配出來。 (2)提取匹配文字 在SAS正則表達式中還遇到了新的問題:
這是一份新的產品列表,現在多了最后一行,這一行是產品的名字和數字編碼放在一起了,我只想要數字編碼的部分,即紅色部分,前面的不想要,怎么辦? 第一部分中介紹了search()提取了匹配部分的開頭和結尾部分,這個一定可以幫我解決! 先把數據讀入Pandas,仍然命名為production: 解決代碼如下:
結果如下: (3)提取匹配文字中的一部分 剛剛對于這個例子:
(01)1872-8756 Body shop P1 Book B13 (05)9212-0098 PD(05)9206-4571 Shushuo phone (12) 6753-5513 None here PD(12)6434-4532 P&D Washing PC Pro4321S: (09) 1352-3154
我成功的寫了一個正則表達式,提取出來匹配的部分,元字符為: P?D?\D\d{2}\D\s?\d{4}-\d{4} 這個表達式和紅色字體部分是對應的。那么有一個問題,假如我想提取出來這段匹配文字的任一部分呢?比如(09) 1352-3154這個括號里的數字,按照情節設定,括號里的數字代表產品的類型,現在想把它提取出來。 和SAS一樣,同樣用“打包”的思路,前面已經學過在Python中如何打包了:
哎呀,只有一列,我不知道每個數字跟原來的哪個對應啊,我得把原數據也加上:
這樣,原數據也有,打包的部分也有了,結果如下: (4)總結 雖然具體的問題千奇百怪,但核心的方法都是一樣的,正則表達式函數+迭代 = Pandas數據的處理??简灥倪€是Python技巧的綜合運用。 做個小游戲,您覺得本【統計師的Python日記】系列如何? 1、不好——跳轉至A 2、好——跳轉至2.1 2.1 打賞嗎? 打賞——跳轉至B 不打賞——跳轉至2.2 2.2 點擊文末廣告? 點擊——跳轉至C 不點擊——跳轉至A A 有什么建議意見呢?您可以在文末評論區留言,幫我做的越來越好! B 謝謝爺~!勞駕您在文末打賞,我會再接再厲噠! C 謝謝小哥,謝謝美女~!廣告商會給我打賞噠! |
|
來自: 三郞 > 《統計師的Python日記》