Python for Data Analysis VI

Posted by Gloomymoon on 2017-01-02

7.4 字符串操作

字符串对象方法

对于大部分字符串操作应用而言,python内置的字符串对象方法已经能够满足要求,例如split拆分、strip修剪空白符、+号连接字符串、join连接列表或元组、in, index, find方法定位子串、count方法返回子串出现次数、replace方法实现模式替换等等。

正则表达式

Python内置的re模块负责对字符串应用正则表达式,re模块的函数可以分为三类:模式匹配、替换以及拆分。一个regex描绘了需要在文本中定位的一个模式,例如标会一个或多个空白符的regex\s+,为了便于重用,可以用re.compile编译一个regex对象。下面是regex的一些用法说明:

1
2
3
4
5
6
7
import re
regex = re.compile('\s+\') # 编译一个可重用的regex对象
regex.split(text) # 对text字符串按照regex进行拆分,获得一个拆分后的数组
regex.findall(text) # 获取text中匹配regex的所有模式,也是一个数组
regex.search(text) # 返回第一个匹配的模式,返回匹配的开始和结束位置
regex.match(text) # 只匹配text字符串首部的模式
regex.sub(replacement, text) # 将text中匹配到的模式替换为replacement

另外如果不仅要找到匹配的模式,还想将模式分段输出,可以将模式待分段的各部分用圆括号包起来。

1
2
3
4
5
pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
# re.IGNORECASE makes the regex case-insensitive
regex = re.compile(pattern, flags=re.IGNORECASE)
m = regex.match('wesm@bright.net')
m.groups()

Output:

1
('wesm', 'bright', 'net')

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

1
2
3
4
5
6
7
8
regex = re.compile(r"""
(?P<username>[A-Z0-9._%+-]+)
@
(?P<domain>[A-Z0-9.-]+)
\.
(?P<suffix>[A-Z]{2,4})""", flags=re.IGNORECASE|re.VERBOSE)
m = regex.match('wesm@bright.net')
m.groupdict()

Output:

1
{'domain': 'bright', 'suffix': 'net', 'username': 'wesm'}

pandas中矢量化的字符串函数

回到数据清理工作中,在分析前常常要做一些字符串规整化工作,包括处理缺失数据。

1
2
3
data = {'Dave': 'dave@google.com', 'Steve': 'steve@gmail.com',
'Rob': 'rob@gmail.com', 'Wes': np.nan}
data = Series(data)

虽然所有的字符串和正则表达式方法都能通过data.map方法应用于各个值,但是如果存在上述数据中的NA就会报错。为了解决这个问题,Series提供了一些能够跳过NA值的字符串操作方法。

1
data.str.contains('gmail')

Output:

1
2
3
4
5
Dave     False
Rob True
Steve True
Wes NaN
dtype: object

同样支持增则表达式和相应的re选项。

1
2
matches = data.str.match(pattern, flags=re.IGNORECASE)
matches

Output:

1
2
3
4
5
Dave     (dave, google, com)
Rob (rob, gmail, com)
Steve (steve, gmail, com)
Wes NaN
dtype: object