1.字符存取方法会返回相应数据的Nullable类型(即Int,String,Float等),这一类型数据不会随缺失值的存在而改变类型;而object会随缺失值的存在而改变返回其他类(整型列转为浮点;而字符由于无法转化为浮点,因此只能归并为object类型)
2.某些Series方法不能在string上使用,例如: Series.str.decode(),因为存储的是字符串而不是字节
3.string类型在缺失值存储或运算时,类型会广播为pd.NA,而不是浮点型np.nan
如果将一个其他类型的容器直接转换string类型可能会出错:
pd.Series([1,'1.']).astype('string')
#报错
pd.Series([1,2]).astype('string')
#报错
pd.Series([True,False]).astype('string')
#报错
当下正确的方法是分两部转换,先转为str型object,在转为string类型:
pd.Series([True,False]).astype('str').astype('string')
#output:
0 1
1 1.
dtype: string
pd.Series([1,2]).astype('str').astype('string')
#output:
0 1
1 2
dtype: string
pd.Series([True,False]).astype('str').astype('string')
#output:
0 True
1 False
dtype: string
#原数据:
0 a_b_c
1 c_d_e
2 <NA>
3 f_g_h
dtype: string
根据某一个元素分割,默认为空格
s.str.split('_')
#output:
0 [a, b, c]
1 [c, d, e]
2 <NA>
3 [f, g, h]
dtype: object
这里需要注意split后的类型是object,因为现在Series中的元素已经不是string,而包含了list,且string类型只能含有字符串。
此方法下可以进行元素的提取:
如果该单元格元素是列表,那么str[i]表示取出第i个元素;
如果是单个元素,则先把元素转为列表再取出。
s.str.split('_').str[1]
# output:
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)
#output:
0 1 2
0 a b c
1 c d e
2 <NA> <NA> <NA>
3 f g h
s.str.split('_',n=1)
#output:
0 [a, b_c]
1 [c, d_e]
2 <NA>
3 [f, g_h]
dtype: object
s.str.split('_',expand=True,n=1)
#output:
0 1
0 a b_c
1 c d_e
2 <NA> <NA>
3 f g_h
cat方法对于不同对象的作用结果并不相同,其中的对象包括:单列、双列、多列
是指所有的元素进行字符合并为一个字符串
# 生成Series:
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0 ab
1 <NA>
2 d
dtype: string
#合并:
s.str.cat()
#output:
‘abd'
sep分隔符参数
s.str.cat(sep=',')
#output:
'ab,d'
缺失值替代字符na_rep参数
s.str.cat(sep=',',na_rep='*')
#output:
'ab,*,d'
是对应索引的元素进行合并
# 生成第一个Series:
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0 ab
1 <NA>
2 d
dtype: string
# 生成第二个Series:
s2 = pd.Series(['24',None,None],dtype='string')
#output:
0 24
1 <NA>
2 <NA>
dtype: string
# 合并:
s.str.cat(s2)
#output:
0 ab24
1 <NA>
2 <NA>
dtype: string
注意:缺失值pd.NA与任何值合并都为pd.NA本身
相应的sep参数与na_rep参数的应用:
合并后的两个缺失值会被同时替换成参数指定的相应字符
s.str.cat(s2,sep=',',na_rep='*')
#output:
0 ab,24
1 *,*
2 d,*
dtype: string
③ 多列拼接可以分为表的拼接和多Series拼接
表的拼接
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0 ab
1 <NA>
2 d
dtype: string
df = pd.DataFrame({0:['1','3','5'],1:['5','b',None]},dtype='string')
# output:
0 1
0 1 5
1 3 b
2 5 <NA>
s.str.cat(df,na_rep='*')
# output:
0 ab15
1 *3b
2 d5*
dtype: string
多个Series拼接
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0 ab
1 <NA>
2 d
dtype: string
s+'0'
#output:
0 ab0
1 <NA>
2 d0
dtype: string
s*2
#output:
0 abab
1 <NA>
2 dd
dtype: string
# 拼接:
s.str.cat([s+'0',s*2])
#output:
0 abab0abab
1 <NA>
2 dd0dd
dtype: string
如果两边合并的索引不相同且未指定join参数,默认为左连接,设置join=‘left’
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0 ab
1 <NA>
2 d
dtype: string
s2 = pd.Series(list('abc'),index=[1,2,3],dtype='string')
#output:
1 a
2 b
3 c
dtype: string
# 合并:
s.str.cat(s2,na_rep='*')
#output:
0 ab*
1 *a
2 db
dtype: string
#因为是默认左链接,所以合并后的结果的index和s的index相同,s2中‘3’被忽略。
r前缀,不用考虑转义的问题:
比如我们匹配信息item\n 时,如果没有r,我们要将正则表达式写成re.compile(‘item\n’);但是,当我们加上了r时,我们的正则表达式写成re.compile(r’item\n’)就可以了。
^表示行的开头
$表示行的结尾
小括号()的意思是将某一部分分开成n个子组
同时可以利用?P<…>表达式对子组命名调用,尖括号里面填子组的名字。
[./-+]
在[]内均表示字符本身;
在[]外特殊字符,表示匹配特殊字符本身,必须要加反斜杠;
或者用r方法
\w表示[0-9a-zA-Z_]
[]+,‘+’号在[]外表示{1,},即1次或多次
‘?’ 匹配前面的子表达式零次或一次。
例如,“do(es)?”可以匹配“does”中的“do”和“does”。?等价于{0,1}。
正则表达式[\w]+,\w+,[\w+] 三者的区别
[\w]+和\w+没有区别,都是匹配多个数字、字母以及下划线;
[\w+]表示匹配一个数字、字母、下划线或加号本身字符;
[ ]表示数组而非排列,即不按固定次序位置排列,在[ ]内的字符可以任意次序出现。
例如:
[ABC]+
可以匹配"AAABBBCCC,BBBAAACCC,BACCBACAACBAC,…",不是一定按固定A…B…C…的次序排列。
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca','', np.nan, 'ABBA', 'dog', 'cat'],dtype="string")
#output:
0 A
1 B
2 C
3 Aaba
4 Baca
5
6 <NA>
7 ABBA
8 dog
9 cat
dtype: string
第一个值写r开头的正则表达式,后一个写替换的字符串
s.str.replace(r'^[AB]','***')
#output:
0 ***
1 ***
2 C
3 ***aba
4 ***aca
5
6 <NA>
7 ***BBA
8 dog
9 cat
dtype: string
s.str.replace(r'^[AB]+','***')
#output:
0 ***
1 ***
2 C
3 ***aba
4 ***aca
5
6 <NA>
7 ***
8 dog
9 cat
dtype: string
写以$结尾的正则表达式,后一个写替换的字符串
s.str.replace(r'[AB]$','***')
#output:
0 ***
1 ***
2 C
3 Aaba
4 Baca
5
6 <NA>
7 ABB***
8 dog
9 cat
dtype: string
通过正整数调用子组(0返回字符本身,从1开始才是子组)
s.str.replace(r'([ABC])(\w+)',lambda x:x.group(2)[1:]+'*')
#output:
0 A
1 B
2 C
3 ba*
4 ca*
5
6 <NA>
7 BA*
8 dog
9 cat
dtype: string
利用?P<…>表达式可以对子组命名调用
s.str.replace(r'(?P[ABC])(?P\w+)' ,lambda x:x.group('two')[1:]+'*')
#output:
0 A
1 B
2 C
3 ba*
4 ca*
5
6 <NA>
7 BA*
8 dog
9 cat
dtype: string
str.replace针对的是object类型或string类型,默认是以正则表达式为操作,目前暂时不支持DataFrame上使用
(当前版本不支持)
pd.Series(['A','B'],dtype='string').str.replace(r'[A]',pd.NA)
#报错
pd.Series(['A','B'],dtype='O').str.replace(r'[A]',pd.NA)
#报错
解决办法:此时,可以先转为object类型再转换回来
pd.Series(['A','B'],dtype='string').astype('O').replace(r'[A]',pd.NA,regex=True).astype('string')
#output:
0 <NA>
1 B
dtype: string
如果要以正则表达式替换,需要设置regex=True,该方法通过字典可支持多列替换
pd.Series(['A','B'],dtype='string').replace(r'[A]',pd.NA,regex=True)
#output:
0 A
1 B
dtype: string
pd.Series(['AA','B'],dtype='O').replace(r'[A]',pd.NA,regex=True)
#output:
0 <NA>
1 B
dtype: object
pd.Series(['A',np.nan],dtype='object').str.replace(np.nan,'B')
#报错
pd.Series(['A',pd.NA],dtype='string').str.replace(pd.NA,'B')
#报错
pd.Series(['A',np.nan],dtype='object').replace(np.nan,'B')
#output:
0 A
1 B
dtype: object
pd.Series(['A',pd.NA],dtype='string').replace(pd.NA,'B')
#output:
0 A
1 B
dtype: string
综上,概况的说,除非需要赋值元素为缺失值(转为object再转回来),或者被赋值元素为缺失值,否则请使用str.replace方法。
pd.Series(['10-87', '10-88', '10-89'],dtype="string").str.extract(r'([\d]{2})-([\d]{2})')
#output:
0 1
0 10 87
1 10 88
2 10 89
pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P[\d]{2})-(?P[\d]{2})' )
#output:
name_1 name_2
0 10 87
1 10 88
2 <NA> <NA>
pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P[\d]{2})?-(?P[\d]{2})' )
#output:
name_1 name_2
0 10 87
1 10 88
2 <NA> 89
pd.Series(['10-87', '10-88', '10-'],dtype="string").str.extract(r'(?P[\d]{2})-(?P[\d]{2})?' )
name_1 name_2
0 10 87
1 10 88
2 10 <NA>
s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
s.index
#output:
Index(['A11', 'B22', 'C33'], dtype='object')
单一子组,expand参数为True的情况:
s.str.extract(r'([\w])')
#expand参数有效,返回DataFrame:
0
A11 a
B22 b
C33 c
单一子组,expand参数设置为False的情况:
s.str.extract(r'([\w])',expand=False)
#expand参数有效,返回Series:
A11 a
B22 b
C33 c
dtype: string
多子组,expand参数设置为False的情况:
s.str.extract(r'([\w])([\d])',expand=False)
#expand参数无效,返回DataFrame:
0 1
A11 a 1
B22 b 2
C33 c 3
单一子组,expand参数为True的情况:
s.index.str.extract(r'([\w])')
#expand参数有效,返回DataFrame:
0
0 A
1 B
2 C
单一子组,expand参数为False的情况:
s.index.str.extract(r'([\w])',expand=False)
#expand参数有效,返回提取后的的index:
Index(['A', 'B', 'C'], dtype='object')
多子组,expand参数为True的情况:
s.index.str.extract(r'([\w])([\d])')
#expand参数有效,返回DataFrame:
0 1
0 A 1
1 B 2
2 C 3
多子组,expand参数为False的情况:
s.index.str.extract(r'([\w])([\d])',expand=False)
#报错
s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"],dtype="string")
two_groups = '(?P[a-z])(?P[0-9])'
s.str.extract(two_groups, expand=True)
#output:
letter digit
A a 1
B b 1
C c 1
s.str.extractall(two_groups)
#output:
letter digit
match
A 0 a 1
1 a 2
B 0 b 1
C 0 c 1
s['A']='a11'
s.str.extractall(two_groups)
#output:
letter digit
match
A 0 a 1
B 0 b 1
C 0 c 1
s = pd.Series(["a1a2", "b1b2", "c1c2"], index=["A", "B", "C"],dtype="string")
s.str.extractall(two_groups).xs(1,level='match')
#output:
letter digit
A a 2
B b 2
C c 2
作用为检测是否包含某种正则模式
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains(r'[0-9][a-z]')
#output:
0 False
1 <NA>
2 True
3 True
4 True
dtype: boolean
a) 可选参数为na
当na=True时,缺失值为True,当na=False时,则相反。不放入na参数,缺失值显示其本身。
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains('a',na=False)
#output:
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)
#output:
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)
#output
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()
#output:
Index(['space1', 'space2', 'space3'], dtype='object')
pd.Series('A',dtype="string").str.lower()
#output:
0 a
dtype: string
pd.Series('a',dtype="string").str.upper()
#output:
0 A
dtype: string
表示交换字母大小写
pd.Series('abCD',dtype="string").str.swapcase()
#output:
0 ABcd
dtype: string
大写首字母
pd.Series('abCD',dtype="string").str.capitalize()
#output:
0 Abcd
dtype: string
检查每一位是否都是数字
pd.Series(['1.2','1','-0.3','a',np.nan],dtype="string").str.isnumeric()
#output:
0 False
1 True
2 False
3 False
4 <NA>
dtype: boolean