python 字符串处理

本文参考《利用python进行数据分析》第七章中字符串操作部分内容

内置的字符串对象方法

  • 分隔符拆分字符串
  • 去空格/换行符
  • 字符串连接
  • 查询子串
  • 子串出现次数
  • 字符串替换
  • Python 内置的字符串方法

分隔符拆分字符串

In [1]: val = 'Machine learning, Data analysis.'

#按逗号分割
In [2]: val.split(',')
Out[2]: ['Machine learning', ' Data analysis.']

#按空格分割
In [3]: val.split(' ')
Out[3]: ['Machine', 'learning,', 'Data', 'analysis.']

去空格/换行符

In [4]: [x.strip() for x in val.split(',')]
Out[4]: ['Machine learning', 'Data analysis.']

可见strip()方法去除的是字符串两端的空格。

字符串连接

#加号连接
In [5]: pieces = ['a','b','c']
In [6]: first, second, third = pieces

In [7]: first+second+third
Out[7]: 'abc'

In [8]: first+':'+second+':'+third
Out[8]: 'a:b:c'

#更加便捷的方法
In [9]: ':'.join(pieces)
Out[9]: 'a:b:c'

查询子串

#in 成员运算符
In [10]: 'Data' in val
Out[10]: True

#index 返回首字母起始位置,**没有找到引发ValueError**
In [11]: val.index('learning')
Out[11]: 8

In [12]: val.index('d')
Out[12]: ValueError: substring not found

#find 返回首字母起始位置,**没有找到返回-1**
In [13]: val.find('learning')
Out[13]: 8

In [14]: val.find('d')
Out[14]: -1

#in和index也可用在列表中,**列表不可以**
In [15]: 'a' in pieces
Out[15]: True

In [16]: pieces.index('b')#列表索引从0开始
Out[16]: 1

In [17]: pieces.find('a')
AttributeError: 'list' object has no attribute 'find'

子串出现次数

In [18]: val.count('a')
Out[18]: 6

字符串替换

In [19]: val.replace('a','A')
Out[19]: 'MAchine leArning, DAtA AnAlysis.'

#传入空字符串可以删除模式
In [20]: val.replace(',',' ')
Out[20]: 'Machine learning  Data analysis.'

Python 内置的字符串方法

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

正则表达式

正则表达式(regex)提供了一种灵活的在文本中搜索或匹配字符串模式的方式。对应python中的re模块。

  • 模式匹配
  • 替换
  • 拆分

拆分(split)

拆分字符串,分隔符为数量不一定的一组空白符(空格、制表符、换行符)。描述一个或多个空白符的regex是\s+

In [1]:import re
In [2]: text = 'Machine   learning\t, Data \tanalysis.'
In [3]: regex = re.compile('\s+')
In [4]: regex.split(text)
Out[4]: ['Machine', 'learning', ',', 'Data', 'analysis.']

匹配字符串中的空白符

In [5]: regex.findall(text)
Out[5]: ['   ', '\t', ' ', ' \t']
  • 对多条字符串应用同一正则表达式,首先通过re.compile()创建regex对象可以节省大量CPU时间。
  • 如果想避免正则表达式中不必要的转义(\),可以使用原始字符串的字面量如r’C:\x’(也可以编写其等价式’C:\x‘)

模式匹配(findall/search/match)

  • findall:返回字符串的所有匹配项
  • search:返回第一个匹配项(以特殊的匹配对象形式返回,匹配对象可以告诉我们模式在原字符串中的起始和结束位置)
  • match:匹配字符串的首部

电子邮件的例子:

In [6]: text = '''Dave Dave0214@google.com
Bob Bob_1996@hotmail.com
Mary MarySun@yahoo.com
Sun SunShine993@qq.com
'''
In [7]: pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'

#flags = re.IGNORECASE表示大小写不敏感
In [8]: regex = re.compile(pattern, flags = re.IGNORECASE)

#findall
In [9]: regex.findall(text)
Out[9]: ['Dave0214@google.com',
 'Bob_1996@hotmail.com',
 'MarySun@yahoo.com',
 'SunShine993@qq.com']

#search 返回一个特殊匹配对象
In [10]: m = regex.search(text)

#模式在原字符串中的起始和结束位置
In [11]: text[m.start():m.end()]
Out[11]: 'Dave0214@google.com'

#match
In [12]: print regex.match(text)
Out[12]: None

替换(sub)

将匹配到的字符串替换为指定字符串

In [13]: print regex.sub('pass',text)
Dave pass
Bob pass
Mary pass
Sun pass

分组模式

#分组模式:用括号将每段括起来
In [14]: pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'

#flags = re.IGNORECASE表示大小写不敏感
In [15]: regex = re.compile(pattern, flags = re.IGNORECASE)

#findall返回元组列表
In [16]: regex.findall(text)
Out[16]: 
[('Dave0214', 'google', 'com'),
 ('Bob_1996', 'hotmail', 'com'),
 ('MarySun', 'yahoo', 'com'),
 ('SunShine993', 'qq', 'com')]

#match+groups 返回一个由模式各段组成的元组
In [17]: m = regex.match('Alia1123@163.com')

In [18]:m.groups()
Out[18]: ('Alia1123', '163', 'com')

访问分组 (sub)

In [19]: print regex.sub(r'Username: \1, Domain: \2, Suffix: \3',text)
Dave Username: Dave0214, Domain: google, Suffix: com
Bob Username: Bob_1996, Domain: hotmail, Suffix: com
Mary Username: MarySun, Domain: yahoo, Suffix: com
Sun Username: SunShine993, Domain: qq, Suffix: com

匹配分组加名称

In [20]: pattern = r'''
(?P<username>[A-Z0-9._%+-]+)
@
(?P<domain>[A-Z0-9.-]+)
\.
(?P<suffix>[A-Z]{2,4})'''
In [21]: regex = re.compile(pattern, flags = re.IGNORECASE|re.VERBOSE)
In [22]: m = regex.match('Alia1123@163.com')

#得到一个带有分组名字的字典
In [23]: m.groupdict()
Out[23]: {'domain': '163', 'suffix': 'com', 'username': 'Alia1123'}

正则表达式方法

方法说明
findall, finditer返回字符串中所有非重叠匹配模式,findall返回的是由所有模式组成的列表,finditer是通过一个迭代器逐个返回。
match从字符串起始位置匹配模式,还可以对模式各部分进行分组。如果匹配到模式,则返回一个匹配项对象,否则返回None。
search扫描整个字符串以匹配模式,如果找到则返回一个匹配项对象,跟match不同,其匹配项可以位于字符串任意位置,而不仅仅是起始处。
split根据模式将字符串拆分成数段
sub, subn将字符串中所有的(sub)或前n个(subn)替换为指定表达式(字符串或函数返回值),在替换字符串中可以使用\1,\2等符号表示各分组项

pandas中矢量化的字符串数组

字符串列含有缺失数据

In [24]: import numpy as np
In [25]: from pandas import Series

In [26]: data = {'Dave':'Dave0214@google.com',
'Bob': 'Bob_1996@hotmail.com',
'Mary': 'MarySun@yahoo.com',
'Sun': np.nan}
In [27]: data = Series(data)
In [28]: data
Out[28]: 
Bob     Bob_1996@hotmail.com
Dave     Dave0214@google.com
Mary       MarySun@yahoo.com
Sun                      NaN
dtype: object

In [29]: data.isnull()
Out[29]: 
Bob     False
Dave    False
Mary    False
Sun      True
dtype: bool

Series的map方法可以使字符串和正则表达式方法都能被应用于(传入lambda表达式或其他函数)各个值,但是如果存在NA值就会报错。因此,通过Series的str属性即可访问一些方法,这些方法可以跳过NA值。
使用str.contains检验各个邮件地址中是否含有hotmail

In [30]: data.str.contains('hotmail')
Out[30]: 
Bob      True
Dave    False
Mary    False
Sun       NaN
dtype: object

也可以使用正则表达式

In [31]: pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
In [32]: data.str.findall(pattern,flags = re.IGNORECASE)
Out[32]: 
Bob     [(Bob_1996, hotmail, com)]
Dave     [(Dave0214, google, com)]
Mary       [(MarySun, yahoo, com)]
Sun                            NaN
dtype: object

str.get或str上使用索引可以实现矢量化的元素获取操作(与书上例子结果不同)

In [33]: matches = data.str.match(pattern, flags=re.IGNORECASE)
In [34]: matches
Out[34]: 
Bob     True
Dave    True
Mary    True
Sun      NaN
dtype: object

#matches.str.get(1)
#matches.str[0]

字符串截取

In [35]: data.str[:5]
Out[35]: 
Bob     Bob_1
Dave    Dave0
Mary    MaryS
Sun       NaN
dtype: object

矢量化的字符串方法

方法说明
cat实现元素级的字符串连接操作,可指定分隔符
contains返回表示各字符串是否含有指定模式的布尔型数组
count模式的出现次数
endswith,startswith相当于对每个元素执行x.endswith(pattern)或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、付费专栏及课程。

余额充值