Pandas玩转文本处理

数据处理,也是风控非常重要的一个环节,甚至说是模型成败的关键环节。因此,娴熟简洁的数据处理技巧,是提高建模效率和建模质量的必要能力。

 向量化操作的概述

对于文本数据的处理(清洗),是现实工作中的数据时不可或缺的功能,在这一节中,我们将介绍Pandas的字符串操作。Python内置一系列强大的字符串处理方法,但这些方法只能处理单个字符串,处理一个序列的字符串时,需要用到for循环。

那么,有没有办法,不用循环就能同时处理多个字符串呢,Pandas的向量化操作(vectorized string operation)就提供了这样的方法。Pandas为可能存在字符串的Series和Index对象提供了str属性,不仅能够进行向量化操作,还能够处理缺失值。

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

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

s = pd.Series(['amazon','alibaba','baidu'])
s.str.count('a')
0    2
1    3
2    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.0
1    3.0
2    1.0
3    NaN
dtype: float64

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

 向量化的字符串处理方法

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

下面选取部分函数举例,其他函数参考字符串模块

1、len()

import pandas as pd
import numpy as np 
 
s = pd.Series(['amazon','alibaba','Baidu'])
s.str.len()
0    6
1    7
2    5

2、lower()

大小写转换,转换成小写字母

s = pd.Series(['Amazon','alibaba','Baidu'])
s.str.lower()
0     amazon
1    alibaba
2      baidu

3、zfill()

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

s = pd.Series(['56783','34','987766721','326'])
s.str.zfill(10) 
0    0000056783
1    0000000034
2    0987766721
3    0000000326

字符串的方法很多,这里就不一一举例了,大家可以参考字符串处理的文章。

 

向量化的正则表达式

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

1、split()

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

1)基本用法

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.split.html

Series.str.split(pat=None,
                 n=- 1, 
                 expand=False, *, 
                 regex=None )

2)参数解释

pat:str 或编译的正则表达式,可选。要拆分的字符串或正则表达式。如果未指定,则在空格处拆分。

n:int,默认 -1(全部)。限制输出中的拆分数量, None , 0 和 -1 将被解释为返回所有拆分。

expand:布尔值,默认为 False。将拆分的字符串展开为单独的列。

  • 如果 True ,返回 DataFrame/MultiIndex 扩展维度。

  • 如果 False ,则返回包含字符串列表的系列/索引。

regex:布尔值,默认无。确定 passed-in 模式是否为正则表达式:

  • 如果 True ,假设 passed-in 模式是正则表达式

  • 如果 False ,则将模式视为文字字符串。

  • 如果 None 和 pat 长度为 1,则将 pat 视为文字字符串。

  • 如果 None 和 pat 长度不为 1,则将 pat 视为正则表达式。

  • 如果 pat 是已编译的正则表达式,则不能设置为 False

注 意:n 关键字的处理取决于找到的拆分数量:

  • 如果发现拆分 > n ,请先进行 n 拆分

  • 如果发现拆分 n ,则进行所有拆分

  • 如果对于某一行,找到的拆分数 n ,则追加 None 以填充到 n if expand=True

如果使用 expand=True ,Series 和 Index 调用者分别返回 DataFrame 和 MultiIndex 对象。使用带有pat 的regex=False 作为编译的正则表达式会引发错误。

3)案例分析

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

# 按固定字符分割
s = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'])
s.str.split('_')

0    [a, b, c]
1    [c, d, e]
2          NaN
3    [f, g, h]


#切分后的列表中的元素可以通过get方法或者 [] 方法进行读取
s.str.split('_').str.get(1)
Out[96]: 
0      b
1      d
2    NaN
3      g

#使用expand方法可以轻易地将这种返回展开为一个数据表
s.str.split('_', expand=True)
     0    1    2
0    a    b    c
1    c    d    e
2  NaN  NaN  NaN
3    f    g    h

#同样,我们也可以限制切分的次数:
s.str.split('_', expand=True, n=1)
     0    1
0    a  b_c
1    c  d_e
2  NaN  NaN
3    f  g_h

2、rsplit()

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

1)基础用法

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.rsplit.html

Series.str.rsplit(pat=None, n=- 1, expand=False)

2)参数解释

pat:str 或编译的正则表达式,可选。要拆分的字符串或正则表达式。如果未指定,则在空格处拆分。

n:int,默认 -1(全部)。限制输出中的拆分数量。None , 0 和 -1 将被解释为返回所有拆分。

expand:布尔值,默认为 False。将拆分的字符串展开为单独的列。

  • 如果 True ,返回 DataFrame/MultiIndex 扩展维度。

  • 如果 False ,则返回包含字符串列表的系列/索引。

3)案例分析

s = pd.Series(['QQ1252号码','QQ1353加我','我389的'])
s.str.rsplit('_', expand=True, n=1)
     0    1
0  a_b    c
1  c_d    e
2  NaN  NaN
3  f_g    h

3、replace ()

1)基本用法

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.replace.html

Series.str.replace(pat, repl, n=- 1, case=None, flags=0, regex=None)

2)参数解释

pat:str 或编译的正则表达式,字符串可以是字符序列或正则表达式。

repl:str 或可调用,替换字符串或可调用对象。可调用对象传递正则表达式匹配对象,并且必须返回要使用的替换字符串。

n:int,默认 -1(全部)从一开始就更换的数量。

case:布尔值,默认无。确定替换是否区分大小写:

  • 如果为 True,则区分大小写(如果 pat 是字符串,则默认为)

  • 设置为 False 不区分大小写

  • 如果 pat 是已编译的正则表达式,则无法设置。

flags:int,默认 0(无标志)。正则表达式模块标志,例如重新忽略。如果 pat 是已编译的正则表达式,则无法设置。

regex:布尔值,默认为真。确定 passed-in 模式是否为正则表达式:

  • 如果为 True,则假定 passed-in 模式是正则表达式。

  • 如果为 False,则将模式视为文字字符串

  • 如果 pat 是已编译的正则表达式或 repl 是可调用的,则不能设置为 False。

3)案例分析

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           A
1           B
2           C
3    XX-XX ba
4    XX-XX ca
5            
6         NaN
7    XX-XX BA
8      XX-XX 
9     XX-XX t

pd.Series(['foo', 'fuz', np.nan]).str.replace('f.', 'ba', regex=True)
0    bao
1    baz
2    NaN


pd.Series(['f.o', 'fuz', np.nan]).str.replace('f.', 'ba', regex=False)
0    bao
1    fuz
2    NaN

4、findall()

1)基础用法

Series.str.findall(pat, flags=0)

2)参数解释

pat:正则表达式

flags:Flags from re module, e.g. re.IGNORECASE (default is 0, which means no flags),是否忽略大小写。

3)案例分析

import re
#提取聊天记录中的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]


s.str.findall('Q')
0    [Q, Q]
1    [Q, Q]
2       [Q]
3       [Q]
4       [Q]

s.str.findall('q')
0    []
1    []
2    []
3    []
4    []

s.str.findall('q', flags=re.IGNORECASE)

0    [Q, Q]
1    [Q, Q]
2       [Q]
3       [Q]
4       [Q]

猜你喜欢

转载自blog.csdn.net/JACK_SUJAVA/article/details/129957253