文本數據是指不能參與算術運算的任何字符,也稱爲字符型數據。如英文字母、漢字、不做爲數值使用的數字(以單引號開頭)和其餘可輸入的字符。python
文本數據具備數據維度高、數據量大且語義複雜等特色,是一種較爲複雜的數據類型。今天,咱們就來一塊兒看看如何使用Pandas對文本數據進行數據處理。git
本文目錄
正則表達式
1. string類型的性質api
1.1. string與object的區別app
1.2. string類型的轉換ide
2. 拆分與拼接函數
2.1. str.split方法編碼
2.2. str.cat方法spa
3. 替換3d
3.1. str.replace的常見用法
3.2. 子組與函數替換
3.3. 關於str.replace的注意事項
4. 字串匹配與提取
4.1. str.extract方法
4.2. str.extractall方法
4.3. str.contains和str.match
5. 經常使用字符串方法
5.1. 過濾型方法
5.2. isnumeric方法
6. 問題及練習
6.1. 問題
6.2. 練習
首先,導入須要使用的包
import pandas as pdimport numpy as np
#pd.Series([1,'1.']).astype('string') #報錯#pd.Series([1,2]).astype('string') #報錯#pd.Series([True,False]).astype('string') #報錯
pd.Series([1,'1.']).astype('str').astype('string')
0 1
1 1
dtype: string
pd.Series([1,2]).astype('str').astype('string')
0 1
1 2
dtype: string
pd.Series([True,False]).astype('str').astype('string')
0 True
1 False
dtype: string
s = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'], dtype="string")s
0 a_b_c
1 c_d_e
2 <NA>
3 f_g_h
dtype: string
s.str.split('_')
0 [a, b, c]
1 [c, d, e]
2 <NA>
3 [f, g, h]
dtype: object
s.str.split('_').str[1]
0 b
1 d
2 <NA>
3 g
dtype: object
pd.Series(['a_b_c', ['a','b','c']], dtype="object").str[1] #第一個元素先轉爲['a','_','b','_','c']
0 _
1 b
dtype: object
s.str.split('_',expand=True)
s.str.split('_',n=1)
0 [a, b_c]
1 [c, d_e]
2 <NA>
3 [f, g_h]
dtype: object
s.str.split('_',expand=True,n=1)
2.2 str.cat方法
s = pd.Series(['ab',None,'d'],dtype='string')s
0 ab
1 <NA>
2 d
dtype: string
s.str.cat()
'abd'
s.str.cat(sep=',')
'ab,d'
s.str.cat(sep=',',na_rep='*')
'ab,*,d'
s2 = pd.Series(['24',None,None],dtype='string')s2
0 24
1 <NA>
2 <NA>
dtype: string
s.str.cat(s2)
0 ab24
1 <NA>
2 <NA>
dtype: string
s.str.cat(s2,sep=',',na_rep='*')
0 ab,24
1 *,*
2 d,*
dtype: string
s.str.cat(pd.DataFrame({0:['1','3','5'],1:['5','b',None]},dtype='string'),na_rep='*')
0 ab15
1 *3b
2 d5*
dtype: string
s.str.cat([s+'0',s*2])
0 abab0abab
1 <NA>
2 dd0dd
dtype: string
s2 = pd.Series(list('abc'),index=[1,2,3],dtype='string')s2
1 a
2 b
3 c
dtype: string
s.str.cat(s2,na_rep='*')
0 ab*
1 *a
2 db
dtype: string
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca','', np.nan, 'CABA', 'dog', 'cat'],dtype="string")s
0 A
1 B
2 C
3 Aaba
4 Baca
5
6 <NA>
7 CABA
8 dog
9 cat
dtype: string
s.str.replace(r'^[AB]','***')
0 ***
1 ***
2 C
3 ***aba
4 ***aca
5
6 <NA>
7 CABA
8 dog
9 cat
dtype: string
s.str.replace(r'([ABC])(\w+)',lambda x:x.group(2)[1:]+'*')
0 A
1 B
2 C
3 ba*
4 ca*
5
6 <NA>
7 BA*
8 dog
9 cat
dtype: string
s.str.replace(r'(?P<one>[ABC])(?P<two>\w+)',lambda x:x.group('two')[1:]+'*')
0 A
1 B
2 C
3 ba*
4 ca*
5
6 <NA>
7 BA*
8 dog
9 cat
dtype: string
#pd.Series(['A','B'],dtype='string').str.replace(r'[A]',pd.NA) #報錯#pd.Series(['A','B'],dtype='O').str.replace(r'[A]',pd.NA) #報錯
pd.Series(['A','B'],dtype='string').astype('O').replace(r'[A]',pd.NA,regex=True).astype('string')
0 <NA>
1 B
dtype: string
pd.Series(['A','B'],dtype='string').replace(r'[A]','C',regex=True)
0 A
1 B
dtype: string
pd.Series(['A','B'],dtype='O').replace(r'[A]','C',regex=True)
0 C
1 B
dtype: object
#pd.Series(['A',np.nan],dtype='string').replace('A','B') #報錯
pd.Series(['A',np.nan],dtype='string').str.replace('A','B')
0 B
1 <NA>
dtype: string
pd.Series(['10-87', '10-88', '10-89'],dtype="string").str.extract(r'([\d]{2})-([\d]{2})')
使用子組名做爲列名
pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P<name_1>[\d]{2})-(?P<name_2>[\d]{2})')
利用?正則標記選擇部分提取
pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P<name_1>[\d]{2})?-(?P<name_2>[\d]{2})')
pd.Series(['10-87', '10-88', '10-'],dtype="string").str.extract(r'(?P<name_1>[\d]{2})-(?P<name_2>[\d]{2})?')
(b)expand參數(默認爲True)
s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")s.index
Index(['A11', 'B22', 'C33'], dtype='object')
s.str.extract(r'([\w])')
s.str.extract(r'([\w])',expand=False)
A11 a
B22 b
C33 c
dtype: string
s.index.str.extract(r'([\w])')
s.index.str.extract(r'([\w])',expand=False)
Index(['A', 'B', 'C'], dtype='object')
s.index.str.extract(r'([\w])([\d])')
#s.index.str.extract(r'([\w])([\d])',expand=False) #報錯
s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"],dtype="string")two_groups = '(?P<letter>[a-z])(?P<digit>[0-9])'s.str.extract(two_groups, expand=True)
s.str.extractall(two_groups)
s['A']='a1's.str.extractall(two_groups)
若是想查看第i層匹配,可以使用xs方法
s = pd.Series(["a1a2", "b1b2", "c1c2"], index=["A", "B", "C"],dtype="string")s.str.extractall(two_groups).xs(1,level='match')
4.3 str.contains和str.match
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains(r'[0-9][a-z]')
0 False
1 <NA>
2 True
3 True
4 True
dtype: boolean
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains('a', na=False)
0 False
1 False
2 True
3 False
4 False
dtype: boolean
pd.Series(['1', None, '3a_', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
0 False
1 False
2 True
3 True
4 False
dtype: boolean
pd.Series(['1', None, '_3a', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
0 False
1 False
2 False
3 True
4 False
dtype: boolean
pd.Series(list('abc'),index=[' space1 ','space2 ',' space3'],dtype="string").index.str.strip()
Index(['space1', 'space2', 'space3'], dtype='object')
pd.Series('A',dtype="string").str.lower()
0 a
dtype: string
pd.Series('a',dtype="string").str.upper()
0 A
dtype: string
pd.Series('abCD',dtype="string").str.swapcase()
0 ABcd
dtype: string
pd.Series('abCD',dtype="string").str.capitalize()
0 Abcd
dtype: string
pd.Series(['1.2','1','-0.3','a',np.nan],dtype="string").str.isnumeric()
0 False
1 True
2 False
3 False
4 <NA>
dtype: boolean
# 方法一> ex1_ori = pd.read_csv('data/String_data_one.csv',index_col='人員編號')> ex1_ori.head() 姓名 國籍 性別 出生年 出生月 出生日人員編號 1 aesfd 2 男 1942 8 102 fasefa 5 女 1985 10 43 aeagd 4 女 1946 10 154 aef 4 男 1999 5 135 eaf 1 女 2010 6 24
> ex1 = ex1_ori.copy()> ex1['冒號'] = ':'> ex1['逗號'] = ','> ex1['國人'] = '國人'> ex1['性別2'] = '性別'> ex1['生於'] = '生於'> ex1['年'] = '年'> ex1['月'] = '月'> ex1['日'] = '日'> ID = ex1['姓名'].str.cat([ex1['冒號'], ex1['國籍'].astype('str'), ex1['國人'], ex1['逗號'], ex1['性別2'], ex1['性別'], ex1['逗號'], ex1['生於'], ex1['出生年'].astype('str'), ex1['年'], ex1['出生月'].astype('str'), ex1['月'], ex1['出生日'].astype('str'), ex1['日'] ])> ex1_ori['ID'] = ID> ex1_ori 姓名 國籍 性別 出生年 出生月 出生日 ID人員編號 1 aesfd 2 男 1942 8 10 aesfd:2國人,性別男,生於1942年8月10日2 fasefa 5 女 1985 10 4 fasefa:5國人,性別女,生於1985年10月4日3 aeagd 4 女 1946 10 15 aeagd:4國人,性別女,生於1946年10月15日4 aef 4 男 1999 5 13 aef:4國人,性別男,生於1999年5月13日5 eaf 1 女 2010 6 24 eaf:1國人,性別女,生於2010年6月24日
# 參考答案> dic_year = {i[0]:i[1] for i in zip(list('零一二三四五六七八九'),list('0123456789'))}> dic_two = {i[0]:i[1] for i in zip(list('十一二三四五六七八九'),list('0123456789'))}> dic_one = {'十':'1','二十':'2','三十':'3',None:''}> df_res = df_new['ID'].str.extract(r'(?P<姓名>[a-zA-Z]+):(?P<國籍>[\d])國人,性別(?P<性別>[\w]),生於(?P<出生年>[\w]{4})年(?P<出生月>[\w]+)月(?P<出生日>[\w]+)日')> df_res['出生年'] = df_res['出生年'].str.replace(r'(\w)+',lambda x:''.join([dic_year[x.group(0)[i]] for i in range(4)]))> df_res['出生月'] = df_res['出生月'].str.replace(r'(?P<one>\w?十)?(?P<two>[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'0','10')> df_res['出生日'] = df_res['出生日'].str.replace(r'(?P<one>\w?十)?(?P<two>[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'^0','10')> df_res.head() 姓名 國籍 性別 出生年 出生月 出生日人員編號 1 aesfd 2 男 1942 8 102 fasefa 5 女 1985 10 43 aeagd 4 女 1946 10 154 aef 4 男 1999 5 135 eaf 1 女 2010 6 24
【練習二】 現有一份半虛擬的數據集,第一列包含了新型冠狀病毒的一些新聞標題,請解決如下問題:
ex2.col2.str.rstrip('-`').str.lstrip('/').astype(float).mean()
-0.984
ex2.columns = ex2.columns.str.strip(' ')
## !!!用於尋找髒數據def is_number(x): try: float(x) return True except (SyntaxError, ValueError) as e: return Falseex2[~ex2.col3.map(is_number)]
ex2.col3.str.replace(r'[`\\{]', '').astype(float).mean()