pandas字符串操作

1、字符串对象方法

对于大部分字符串处理应用而言,内置的字符串方法已经能够满足要求了。

(1)split       以逗号分隔的字符串可以用split拆分成数段

val = 'a,b,guido'
val.split(',')
Out[3]: ['a', 'b', 'guido']

(2)strip     split结合strip(用于修剪空白符(包括换行符))一起使用:

pieces = [x.strip() for x in val.split(',')]
pieces
Out[5]: ['a', 'b', 'guido']

(3)加法     连接子字符串

first + '//'+second+'//'+third
Out[8]: 'a//b//guido'

向字符串“//”的join方法传入一个列表或元组:

'::'.join(pieces)
Out[9]: 'a::b::guido'

(4)子串定位      检测子串的最佳方式是利用Python的in关键字,也可以使用index和find

val.index(',')
Out[11]: 1

val.find(',')
Out[12]: 1

val.find(':')
Out[13]: -1

注意:find和index的区别:如果找不到字符串,index将会引发一个异常(而不是返回-1)

(5)count函数      返回指定子串的出现次数

val.count(',')
Out[15]: 2

(6)replace        用于将指定模式替换为另一个模式,也常常用于删除模式:传入空字符串

val.replace(',','::')
Out[16]: 'a::b::guido'

val.replace(',','')
Out[17]: 'abguido'
Python内置的字符串方法
                方法                                    说明
count返回子串在字符串中的出现次数(非重叠)
endswith、startswith如果字符串以某个后缀结尾(以某个前缀开头),则返回True
join将字符串用作连接其他字符串序列的分隔符
index如果在字符串中找到子串,则返回子串第一个字符所在的位置。如果没有找到,则引发ValueError
find如果在字符串中找到子串,则返回第一个发现的子串的第一个字符所在的位置。如果没有找到,则返回-1
rfind如果在字符串中找到子串,则返回最后一个发现的子串的第一个字符所在的位置。如果没有找到,则返回-1
replace用另一个字符串替换指定子串
strip、rstrip、lstrip去除空白符(包括换行符),相当于对各个元素执行x.strip()(以及rstrip、lstrip)
split通过指定的分隔符将字符串拆分为一组子串
lower、upper分别将字母字符转换为大写或小写
ljust、rjust用空格(或其他字符)填充字符串的空白侧以返回符合最低宽度的字符串

2、正则表达式

re模块的函数可以分为三个大类:模式匹配、替换以及拆分。

一个regex描述了需要在文本中定位的一个模式,假设我想要拆分一个字符串,分隔符为数量不定的一组空白符(制表符、空格、换行符),描述一个或多个空白符的regex是\s+:

调用re.split('\s+',text)时,正则表达式会先被编译,然后再在text上调用其split方法。可以用re.compile自己编译regex以得到一个可重用的regex对象:如果打算对许多字符串应用同一条正则表达式,强烈建议通过re.compile创建regex对象。

regex = re.compile('\s+')
regex.split(text)

①如果只希望得到匹配regex的所有模式,则可以使用findall方法:

regex.findall(text)
Out[22]: [' ', '\t ', ' \t']

注意:如果想避免正则表达式中不需要的转义(\),则可以使用原始字符串字面量如r'C:\x'(也可以编写其等价式'C:\\x')

②match和search跟findall功能类似

findall返回的是字符串中所有的匹配项,而search则只返回第一个匹配项。match更加严格,只匹配字符串的首部。

例子:假设有一段文本以及一条能够识别大部分电子邮件地址的正则表达式。

import re
text="""Dave dave@google.com
Steve steve@gmail.com
Rob rob@gmail.com
Ryan ryan@yahoo.com
"""
pattern = r'[A-Z0-9.-]+@[A-Z0=9.-]+\.[A-Z]{2,4}'
regex = re.compile(pattern,flags=re.IGNORECASE)#re.IGNORECASE的作用是使正则表达式对大小写不敏感
regex.findall(text)#对text使用findall将得到一组电子邮件地址
Out[32]: ['dave@google.com', 'steve@gmail.com', 'rob@gmail.com', 'ryan@yahoo.com']

search返回的是文本中第一个电子邮件地址(以特殊的匹配项对象形式返回),对于上面那个regex,匹配项对象只能告诉我们模式在原字符串中的起始和结束位置:

m = regex.search(text)
m
Out[34]: <_sre.SRE_Match object; span=(5, 20), match='dave@google.com'>

text[m.start():m.end()]
Out[35]: 'dave@google.com'

regex.match则将返回None,因为它只匹配出现在字符串开头的模式:

print(regex.match(text))
None

另外还有一个sub方法,它会将匹配到的模式替换为指定字符串,并返回所得到的新字符串:

print(regex.sub('REDACTED',text))
Dave REDACTED
Steve REDACTED
Rob REDACTED
Ryan REDACTED

假设不仅找出电子邮件地址,还想将各个地址分为3个部分:用户名、域名以及域后缀。要想实现此功能,只需将待分段的模式的各部分用括号包起来即可:

pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9._]+)\.([A-Z]{2,4})'
regex = re.compile(pattern,flags=re.IGNORECASE)

由这种正则表达式所产生的匹配项对象,可以通过其groups方法返回一个由模式各段组成的元组:

m = regex.match('wesm@bright.net')
m.groups()
Out[5]: ('wesm', 'bright', 'net')

对于带有分组功能的模式,findall会返回一个元组列表:

regex.findall(text)
Out[6]: 
[('dave', 'google', 'com'),
 ('steve', 'gmail', 'com'),
 ('rob', 'gmail', 'com'),
 ('ryan', 'yahoo', 'com')]

sub还能通过诸如\1、\2之类的特殊符号访问各匹配项中的分组:

print(regex.sub(r'Username:\1,Domain:\2,Suffix:\3',text))
Dave Username:dave,Domain:google,Suffix:com
Steve Username:steve,Domain:gmail,Suffix:com
Rob Username:rob,Domain:gmail,Suffix:com
Ryan Username:ryan,Domain:yahoo,Suffix:com

由这种正则表达式所产生的匹配项对象可以得到一个简单易用的带有分组名称的字典:

m = regex.match('wesm@bright.net')
m.groupdict()
Out[10]: {'username': 'wesm', 'domain': 'bright', 'suffix': 'net'}
正则表达式方法
方法说明
findall、finditer返回字符串中所有的非重叠匹配模式。findall返回的是由所有模式组成的列表,而finditer则通过一个迭代器逐个返回
match从字符串起始位置匹配模式,还可以对模式各部分进行分组。如果匹配到模式,则返回一个匹配项对象,否则返回None
search扫描整个字符串以匹配模式。如果找到则返回一个匹配项对象。跟match不同,其匹配项可以位于字符串的任意位置,而不仅仅是起始处
split根据找到的模式将字符串拆分为数段
sub、subn将字符串中所有的(sub)或前n个(subn)模式替换为指定表达式。在替换字符串中可以通过\1、\2的符号表示各项分组项

3、pandas中矢量化的字符串函数

清理待分析的散乱数据时,常常需要做一些字符串规整化工作。更为复杂的情况是,含有字符串的列有时还含有缺失数据:

data = {'Dave':'dave@google.com','Steve':'steve@gmail.com','Rob':'rob@gmail.com','Wes':np.nan}
data = pd.Series(data)
data
Out[20]: 
Dave     dave@google.com
Steve    steve@gmail.com
Rob        rob@gmail.com
Wes                  NaN
dtype: object

data.isnull()
Out[21]: 
Dave     False
Steve    False
Rob      False
Wes       True
dtype: bool

(1)Series中有一些能够跳过NA值得字符串操作方法

通过Series的str属性即可访问这些方法。例如通过str.contains检查各个电子邮件地址是否含有“gmail”:

data.str.contains('gmail')
Out[23]: 
Dave     False
Steve     True
Rob       True
Wes        NaN
dtype: object

这里也可以使用正则表达式,还可以加上任意re选项(如IGNORECASE):

pattern
Out[24]: '([A-Z0-9._%+-]+)@([A-Z0-9._]+)\\.([A-Z]{2,4})'

data.str.findall(pattern,flags=re.IGNORECASE)
Out[25]: 
Dave     [(dave, google, com)]
Steve    [(steve, gmail, com)]
Rob        [(rob, gmail, com)]
Wes                        NaN
dtype: object

(2)实现矢量化的元素获取操作

①str.get    ②在str属性上使用索引

矢量化的字符串方法
方法说明
cat实现元素级的字符串连接操作,可指定分隔符
contains返回表示各字符串是否含有指定模式的布尔型数组
count模式的出现次数
endswith、startswith相当于对各个元素执行w.endswith(pattern)或x.startswith(pattern)
findall计算各字符串的模式列表
get获取各元素的第i个字符
join根据指定的分隔符将Series中各元素的字符串连接起来
len计算各字符串的长度
lower、upper转换大小写。相当于对各个元素执行x.lower()或x.upper()
match根据指定的正则表达式对各个元素执行re.match
pad在字符串的左边、右边或左右两边添加空白符
center相当于pad(side='both')
repeat重复值。例如,s.str.repeat(3)相当于对各个字符串执行x*3
replace用指定字符串替换找到的模式
slice对Series中的各个字符串进行子串截取
split根据分隔符或正则表达式对字符串进行拆分
strip、rstrip、lstrip去除空白符,包括换行符。相当于对各个元素执行x.strip()、x.rstrip()、x.lstrip()

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值