本文参考《利用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() |