數據處理的其中一個重要技巧是懂得如何透過分隔文字,提取到有用的資訊整合數據。
導入例子
一個簡單的例子是透過搜集自己學校學生的人名,找出哪一個姓氏最為常見和最罕有。我們的數據可能以「’Chan, Tai Man’,’Chan, Yi Man’,’Cheung, Hiu Wing’,…」的方式儲存。
數據已經有我們需要的材料了。可是,我們該如何才能提取每個名字的姓氏,組合成一個新的列表(List)?我們今天的課題就是如何以 Python 分隔文字,製做出如「’Chan’,’Chan’,’Cheung’,…」的結果。
Python 萬用的 str.split() 功能
example_string = 'Chan, Peter|115|46|A'
delimiter = '|'
split_string = example_string.split(delimiter)
print(split_string)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
如果您曾經使用過 Excel 試算表,那麼 split() 這個功能應該不會對您過於陌生。簡單而言,split() 就像是 Excel 裡的資料剖析(Text-to-column),透過提供分隔號(Delimiter),將文字分隔成一個列表(list)。
例如我們的原始數據是 'Chan, Peter|115|46|A'
,代表姓名、身高、體重和血型。假如我們提供 ‘|’ 作為分隔號,所得出的回傳是有 4 個項目的列表:「'Chan, Peter','115','46','A'」
。
Python 的語法如下:
split_string = my_str.split(delimiter)
編程要點:split 的 3 個要點
這個精辟的編程語法有幾個要點:
my_str 是一個文字(string)
妙在您可以直接在文字後面加上 .split()
,例如寫成 'Chan, Peter|115|46|A'.split('|')
。
# 簡短的寫法
split_string = 'Chan, Peter|115|46|A'.split('|')
print(split_string)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
delimiter 也是一個文字(string)
Delimiter 可以是一個字元(例如 , | ; 等),也可以是聯合數個字元一起用。如果把 delimiter 漏空,那麼預設的 delimiter 是一個空格。
# 多個字元的 delimiter
split_string = 'Chan, Peter|^|115|^|46|^|A'.split('|^|')
print(split_string)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
# 沒有提供 delimiter 的時候
split_string = 'Chan, Peter|115|46|A'.split()
print(split_string)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
split_string 是一個列表
假如您的文字沒有所提供的 delimiter,例如 'Chan, Peter|115|46|A'.split(';')
,那麼 Python 會回傳含有一個項目的列表,而這個項目是您所提供的文字。
# 文字沒有出現所提供的 delimiter
split_string = 'Chan, Peter|115|46|A'.split(';')
print(split_string)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
從 split 回傳的列表提取第 N 個項目
透過 split() 獲取了列表之後,我們還要解決最核心的問題,就是如何提取到我們需要的資料。
問題是,我們剛才的回送的結果是一個列表,該如何轉換成一個文字(string)的輸出?
比方說,我們想要獲取 'Chan, Peter|115|46|A'
裡面的人名,該如何設計我們的編程?
重溫列表索引(List Index)編程
基本上,這個問題是一個列表索引(list index)的延伸,就是如何透過指名列表項目的排序(order),獲取我們需要的項目。
列表索引的語法是:
item = list[begin:end:step]
常用的例子
以下蒐集一些個人比較常用的語法,供大家參考。以下例子的原始文字是
。'Chan, Peter|115|46|A'
- 提取順序第 N 的項目,例如第 1 的 ‘Chan, Peter’(記得 Python 列表索引是從 0 開始喔):
result = my_str.split(delimiter)[N-1]
# 提取順序第 N 的項目(留意索引是 N-1)
result = 'Chan, Peter|115|46|A'.split('|')[0]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
- 提取倒序第 N 的項目,例如第 1 的 ‘A’
result = my_str.split(delimiter)[-N]
# 提取倒序第 N 的項目
result = 'Chan, Peter|115|46|A'.split('|')[-1]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
- 同時提取順序第 N 開始計的 M 的項目
result = my_str.split(delimiter)[N-1:M]
# 同時提取順序第 N 開始計的 M 的項目 (這裡 N 是 1,M 是 2)
result = 'Chan, Peter|115|46|A'.split('|')[0:2]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
- 同時提取倒序第 N 開始計的 M 的項目
result = my_str.split(delimiter)[-N-M:-N]
# 同時提取倒序第 N 開始計的 M 的項目 (這裡 N 是 1,M 是 2)
result = 'Chan, Peter|115|46|A'.split('|')[-3:-1]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
- 同時提取順序排序是單數的項目(第 1,3,5 … 項)
result = my_str.split(delimiter)[::2]
# 同時提取順序排序是單數的項目(第 1,3,5 ... 項)
result = 'Chan, Peter|115|46|A'.split('|')[::2]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
更複雜用法可以搭配 List Comprehension 使用,有興趣可以參考這邊:List Comprehension: Python 的 For Loop 怎樣使用?
進階:在文字列表(list of string)使用 split()
學會了基本功之後,我們來學習如何以 split() 處理文字列表的分隔。這部分我們會大量使用 List Comprehension,如果您不知道/還沒學會 List Comprehension 可以參考這邊:List Comprehension: Python 的 For Loop 怎樣使用?
延伸上方的例子,我們現在的數據是「'Chan, Peter|115|46|A'
,'Cheung, Simon|105|60|B'
,'Lam, Tony|125|50|O'
,'Ng, John|130|45|A'
」。現在,我們列表的 4 個項目都是一行數據,而我們需要套用同一組邏輯提取有用的資訊。
Python 的編程語法是:
result = [x.split(delimiter)[N] for x in data]
一個簡單的例子是從以上數據提取每個人的名稱。首先我們發現我們需要以 ‘|’ 作為 delimiter,提取 split() 結果的第一項。再配合 List Comprehension,我們把 .split('|')[0]
的處理套用在列表裡每一個項目上。
完成後,我們會見到回傳的結果是一張新的列表。這張列表含有「'Chan, Peter'
,'Cheung, Simon'
,'Lam, Tony'
,'Ng, John'
」,成功了!
data = ['Chan, Peter|115|46|A', 'Cheung, Simon|105|60|B', 'Lam, Tony|125|50|O', 'Ng, John|130|45|A']
result = [x.split('|')[0] for x in data]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
如果我們進一步,只想提取名(First Name)而捨棄姓氏(Last Name)怎麼辦?小提示:我們可以用 2 次 .split() 喔!想知道答案就於下面的編程示例試試看吧!
data = ['Chan, Peter|115|46|A', 'Cheung, Simon|105|60|B', 'Lam, Tony|125|50|O', 'Ng, John|130|45|A']
result = [(x.split('|')[0]).split(', ')[1] for x in data]
print(result)
註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!
答案呼之欲出,就是我們留意到 ‘Chan, Peter’ 也是一個統一格式(Format)的數據,只要我們吧名字以 ‘, ‘(注意有一個空格)作為 delimiter 即可提取到名(First Name)!
教學完整代碼
最後送給大家這篇教學的 Google Colab 完整代碼。如果您不懂得使用免安裝又好用的 Google Colab Notebook,記得閱讀這篇教學了:新手 1/3:5 分鐘免安裝學習 Python?Google Colab Notebook 幫緊您!
結語
希望以上例子讓您學會更多有關文字切割的強大的用途,以及如何編程寫出適用於您的 split() 數據處理步驟吧!