【Python基础】Pandas向量化字符串操作

共 7758字,需浏览 16分钟

 ·

2020-11-21 05:19

一、向量化操作概述

Python内置一系列强大的字符串处理方法,但这些方法只能处理单个字符串,处理一个序列的字符串时,需要用到循环。

那么,有没有办法,不用循环就能同时处理多个字符串呢,pandas的向量化操作就提供了这样的方法。

向量化的操作使我们不必担心数组的长度和维度,只需要关系操作功能,尤为强大的是,除了支持常用的字符串操作方法,还集成了正则表达式的大部分功能,这使得pandas在处理字符串列时,具有非常大的魔力。

例如,要计算每个单词中‘a’的个数,下面一行代码就可以搞定,非常高效

s = pd.Series(['amazon','alibaba','baidu'])s.str.count('a')0    21    32    1

假如用内置的字符串函数进行操作,需要进行遍历,且Python原生的遍历操作无法处理缺失值。

#用循环进行处理
s = ['amazon','alibaba','baidu'][i.count('a') for i in s][2, 3, 1]

#存在缺失值时,打印报错
s = ['amazon','alibaba','baidu',None][i.count('a') for i in s]AttributeError: 'NoneType' object has no attribute 'lower'

Pandas的向量化操作,能够正确的处理缺失值,无报错信息,如下

s = pd.Series(['amazon','alibaba','baidu',None])s.str.count('a')Out[36]: 0    2.01    3.02    1.03    NaNdtype: float64

通过上面的例子,对向量化进行简单总结,向量化是一种同时操作整个数组而不是一次操作一个元素的方法,下面从看看具体怎么应用。

 


二、向量化的字符方法

Pandas的字符串属的方法几乎包括了大部分Python的内置字符串方法(内置共有45个方法),下面将列举一些常见的方法的用法,例如上面的count()方法将会返回某个字符的个数,而len方法将会返回整个字符的长度。

方法

说明

len()

计算字符串长度

strip()

等价于str.strip,去除字符串开头和结尾处指定的字符

rstrip()

等价于str.rstrip ,删除字符串末尾的指定字符(默认为空格)

lstrip()

等价于str.lstrip,截掉字符串左边的空格或指定字符

partition()

等价于str.partition,根据指定的分隔符(sep)将字符串进行分割,从左边开始

rpartition()

等价于str.rpartition,根据指定的分隔符(sep)将字符串进行分割,从右边开始

lower()

等价于str.lower,所有大写字母转换为小写字母,仅限英文

casefold()

等价于str.casefold,所有大写字母转换为小写字母,包括非英文

upper()

等价于str.upper,小写字母转换为大写字母

find()

等价于str.find,查找字符串中指定的子字符串sub第一次出现的位置

rfind()

等价于str.rfind,查找字符串中指定的子字符串sub最后一次出现的位置

index()

等价于str.index,查找字符串中第一次出现的子字符串的位置

rindex()

等价于str.rindex,返回子字符串最后一次出现在字符串中的索引位置

capitalize()

等价于str.capitalize,将字符串的第一个字母变成大写,其余字母变为小写

swapcase()

等价于str.swapcase,将字符串str中的大小写字母同时进行互换

normalize()

返回Unicode 标注格式。等价于 unicodedata.normalize

translate()

等价于str.translate,根据maketrans()函数给出的字符映射表来转换字符

isalnum()

等价于str.isalnum,检测字符串是否由字母和数字组成

isalpha()

等价于str.isalpha,检测字符串是否只由字母组成

isdigit()

等价于str.isdigit,检测字符串是否只由数字组成

isspace()

等价于str.isspace,检测字符串是否只由空格组成

islower()

等价于str.islower,检测字符串中的字母是否全由小写字母组成

isupper()

等价于str.isupper,检测字符串中的字母是否全由大写字母组成

istitle()

等价于str.istitle,检测所有单词首字母是否为大写,且其它字母是否为小写

isnumeric()

等价于str.isnumeric,测字符串是否只由数字组成

isdecimal()

等价于str.isdecimal,检查字符串是否只包含十进制字符

startswith()

等价于str.startswith(pat),判断字符串是否以指定字符或子字符串开头

endswith()

等价于str.endswith(pat),判断字符串是否以指定字符或子字符串结尾

center()

等价于str.center,即字符串str居中,两边用字符填充

ljust()

等价于str.ljust,左对齐填充,并使用fillchar填充(默认为空格)

rjust()

等价于str.rjust,右对齐填充,默认为空格

zfill()

等价于str.zfill,右对齐,前面用0填充到指定字符串长度

下面选取部分函数举例,其他函数参考字符串模块:Python字符串的45个方法详解

len()

import pandas as pdimport numpy as np  s = pd.Series(['amazon','alibaba','Baidu'])s.str.len()Out[5]: 0    61    72    5dtype: int64

lower()

s = pd.Series(['amazon','alibaba','Baidu'])s.str.lower()0     amazon1    alibaba2      baidu


zfill()

右对齐,前面用0填充到指定字符串长度

s = pd.Series(['56783','34','987766721','326'])s.str.zfill(10) Out[53]: 0    00000567831    00000000342    09877667213    0000000326dtype: object

 

三、向量化的正则表达式

Pandas的字符串方法根据Python标准库的re模块实现了正则表达式,下面将介绍Pandas的str属性内置的正则表达式相关方法

方法

说明

match()

对每个元素调用re.match(),将会返回一个布尔数组

extract()

对每个元素调用re.match(),将会返回所有结果构成的字符串数组

findall()

对每个元素用re.findall()

replace()

用正则模式替换字符串

contains()

对每个元素调用re.search()返回布尔类型

count()

计算符合正则表达式的字符串数量

split()

等价于str.spilt(),支持正则表达式

rsplit()

等价于str.rsplit()支持正则表达式


split()

split,按指定字符分割字符串,类似split的方法返回一个列表类型的序列

#按数字分割
pd.Series(['QQ1252号码','QQ1353加我','我389的']).str.split('\d+')Out[39]: 0    [QQ, 号码]1    [QQ, 加我]2     [我, 的]dtype: object

s=pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'])s.str.split('_')Out[94]: 0 [a, b, c]1 [c, d, e]2 NaN3 [f, g, h]dtype: object

切分后的列表中的元素可以通过get方法或者 [] 方法进行读取

s.str.split('_').str.get(1)Out[96]: 0      b1      d2    NaN3      gdtype: object

使用expand方法可以轻易地将这种返回展开为一个数据表

s.str.split('_', expand=True)Out[97]:      0    1    20    a    b    c1    c    d    e2  NaN  NaN  NaN3    f    g    h

同样,我们也可以限制切分的次数:

In [20]: s.str.split('_', expand=True, n=1)Out[20]:      0    10    a  b_c1    c  d_e2  NaN  NaN3    f  g_h

rsplit()

rsplit与split相似,不同的是,这个切分的方向是反的。即,从字串的尾端向首段切分

In [21]: s.str.rsplit('_', expand=True, n=1)Out[21]:      0    10  a_b    c1  c_d    e2  NaN  NaN3  f_g    h

replace ()

replace方法默认使用正则表达式

s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca','', np.nan, 'CABA', 'dog', 'cat'])

s.str.replace('^.a|dog', 'XX-XX ', case=False)Out[27]: 0 A1 B2 C3 XX-XX ba4 XX-XX ca5 6 NaN7 XX-XX BA8 XX-XX 9 XX-XX t

findall()

提取聊天记录中的QQ号
s=pd.Series(['QQ号码123452124','QQ123356123','我的Q123356189','Q号123356111注意','加我Q号123356124有惊喜'])s.str.findall('\d+')0    [123452124]1    [123356123]2    [123356189]3    [123356111]4    [123356124]

 

四、其他向量化的方法

除了上面介绍的Pandas字符串的正常操作和正则表达式外,Pandas的str属性还提供了其他的一些方法,这些方法非常的有用,在进行特征提取或者数据清洗时,非常高效,具体如下:

方法

说明

get()

获取元素索引位置上的值,索引从0开始

slice()

对元素进行切片取值

slice_replace()

对元素进行切片替换

cat()

连接字符串

repeat()

重复元素

normalize()

将字符串转换为Unicode规范形式

pad()

在字符串的左边右边或者两边增加空格

wrap()

将字符串按照指定的宽度换行

join()

用分隔符连接Series对象的每个元素

get_dummies()

按照分隔符提取每个元素的dummy变量,转换为one-hot编码的DataFrame

wrap()

s = pd.Series(['0000056783','0000000034','0987766721'])s.str.wrap(5)Out[68]: 0    00000\n567831    00000\n000342    09877\n66721dtype: object

pad()

s = pd.Series(['A','E','C','D','E'])s.str.pad(5)Out[65]: 0        A1        E2        C3        D4        Edtype: object

slice()

Series_1 = pd.Series(['马 云:2000亿','马化腾:1800亿','王健林:1200亿','小伍哥:0.000012亿'])Series_1.str.slice(0,3)Out[33]: 0    马 云1    马化腾2    王健林3    小伍哥dtype: object

get()

Series_1.str.get(0)Out[34]: 0    1    2    3    dtype: object

slice_replace()

切片替换
Series_1.str.slice_replace(0,3,'小伍哥')Out[36]: 0        小伍哥:2000亿1        小伍哥:1800亿2        小伍哥:1200亿3    小伍哥:0.000012亿dtype: object

Series_1.str.join('-')Out[41]: 0 马- -云-:-2-0-0-0-亿1 马-化-腾-:-1-8-0-0-亿2 王-健-林-:-1-2-0-0-亿3 小-伍-哥-:-0-.-0-0-0-0-1-2-亿dtype: object
Series_1 = pd.Series(['A','E','C','D','E'])Series_1.str.get_dummies() A C D E0 1 0 0 01 0 0 0 12 0 1 0 03 0 0 1 04 0 0 0

get_dummies()

另一个需要好好解释的是get_dummies()方法,举个例子:假如我们用A,B,C,D来表示一个人的某个特征:

monte = pd.Series(['Graham Chapman', 'John Cleese', 'Terry Gilliam',                   'Eric Idle', 'Terry Jones', 'Michael Palin'])full_monte = pd.DataFrame({'name': monte,                           'info': ['B|C|D', 'B|D', 'A|C',                                    'B|D', 'B|C', 'B|C|D']})full_monte             name   info0  Graham Chapman  B|C|D1     John Cleese    B|D2   Terry Gilliam    A|C3       Eric Idle    B|D4     Terry Jones    B|C5   Michael Palin  B|C|D可以看到比如Graham Chapman有B,C,D三种特征,而John Cleese有B和D两种特征。这时我们可以用get_dummies('|')以|作为分隔符,将这些特征进行one-hotfull_monte['info'].str.get_dummies('|')Out[52]:    A  B  C  D0  0  1  1  11  0  1  0  12  1  0  1  03  0  1  0  14  0  1  1  05  0  1  1  1

repeat()

s = pd.Series(['A','E','C','D','E'])s.str.repeat(2)Out[62]: 0    AA1    EE2    CC3    DD4    EEdtype: object

cat()

作用:连接字符串 

用法:Series.str.cat(others=None, sep=None, na_rep=None) 

参数: 

  • others : 列表或复合列表,默认为None,如果为None则连接本身的元素 

  • sep : 字符串 或者None,默认为None 

  • na_rep : 字符串或者 None, 默认 None。如果为None缺失值将被忽略。 

返回值: concat : 序列(Series)/索引(Index)/字符串(str)

#如果连接的是两个序列,则会一一对应连接s1 = pd.Series(['A','E','C','D','E'])s2 = pd.Series(['1','2','3','4','5'])s1.str.cat(s2)Out[74]: 0    A11    E22    C33    D44    E5dtype: object

#只提供一个序列,则只连接自己,默认为空格s1.str.cat()'AECDE's1.str.cat(sep='-')'A-E-C-D-E'
#也可以同时复核连接,参数可以是二维的d = pd.concat([s1, s2], axis=1)s3.str.cat(d, na_rep='-')Out[87]: 0 xA11 xE22 yC33 yD44 yE5dtype: objec


五、Pandas学习文档

官方文档

链接:https://pandas.pydata.org/pandas-docs/stable/index.html

官方文档,每个函数和方法,都有详细的介绍,对于英语比较好的同学,强烈推荐直接看官方文档,非常清晰,完整。

             


中文文档

文档链接:https://www.pypandas.cn/docs/

对于英语不好的同学,可以看国内翻译过来的文档,还是比较全面的,基本上也能获得比较好的学习效果。

              

接口文档

https://pandas.pydata.org/pandas-docs/version/0.17.0/#

 

往期精彩回顾





获取本站知识星球优惠券,复制链接直接打开:

https://t.zsxq.com/y7uvZF6

本站qq群704220115。

加入微信群请扫码:

浏览 50
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报