公众号:尤而小屋
作者:Peter
编辑:Peter
大家好,我是Peter~
本文介绍Pandas中针对文本数据处理的方法。文本数据也就是我们常说的字符串,Pandas 为 Series 提供了 str 属性,通过它可以方便的对每个元素进行操作。
首先需要清楚的是:Python中原生的字符串操作的相关的函数也是适用的。
import pandas as pd
import numpy as np
模拟数据
df = pd.DataFrame({
"name":["xiao ming","xiao zhang",np.nan,"sun quan","guan yu"],
"age":[22,19,20,34,39],
"sex":["male","Female","female","Female","male"],
"address":[" 广东省 深圳市 ","浙江省 杭州市"," 江苏省苏州市 ","福建省 泉州市","广东省广州市"]
})
df
df.dtypes
name object
age int64
sex object
address object
dtype: object
字母转换函数
在Python原生的字符串转换中有upper、lower、title等函数和字母转换相关
upper
将字母全部转成大写的形式
df["sex"].str.upper()
0 MALE
1 FEMALE
2 FEMALE
3 FEMALE
4 MALE
Name: sex, dtype: object
lower
将字母全部转成小写形式
df["sex"].str.lower()
0 male
1 female
2 female
3 female
4 male
Name: sex, dtype: object
capitalize
第一个单词的首字母大写
df["name"].str.capitalize()
0 Xiao ming
1 Xiao zhang
2 NaN
3 Sun quan
4 Guan yu
Name: name, dtype: object
title
每个单词的首字母大写;注意和capitalize的区别:
df["name"].str.title()
0 Xiao Ming
1 Xiao Zhang
2 NaN
3 Sun Quan
4 Guan Yu
Name: name, dtype: object
swapcase
大小写互换:小写换成大写,反之,大写换成小写
df["name"].str.swapcase()
name原来全部是小写,下面结果全部变成了大写:
0 XIAO MING
1 XIAO ZHANG
2 NaN
3 SUN QUAN
4 GUAN YU
Name: name, dtype: object
df["sex"].str.swapcase()
0 MALE
1 fEMALE
2 FEMALE
3 fEMALE
4 MALE
Name: sex, dtype: object
casefold
lower() 只对 ASCII 也就是 'A-Z'有效;此时casefold()和lower()相同效果
df["sex"].str.lower()
0 male
1 female
2 female
3 female
4 male
Name: sex, dtype: object
df["sex"].str.casefold()
0 male
1 female
2 female
3 female
4 male
Name: sex, dtype: object
但是其它一些语言里面存在小写的情况,lower()函数就不能处理。下面我们用德语中'ß'来区分二者,真实小写是'ss':
s = 'ß'
s.lower()
'ß'
使用casefold函数能够实现:
s.casefold()
'ss'
在对 Series 中每个元素处理时,我们可以使用Pandas中内置的 map 或 apply 方法
df["name"].apply(lambda x: x.upper())
可以看到出现了报错:float类型的数据是没有upper属性的。这是因为数据中出现了NaN,NaN在Pandas中是被当做float类型。
下面使用upper方法来实现转换:当使用str.upper进行转换的时候能够自动排除缺失值的数据。
df["name"].str.upper() # 写法1
df.name.str.upper() # 写法2
0 XIAO MING
1 XIAO ZHANG
2 NaN
3 SUN QUAN
4 GUAN YU
Name: name, dtype: object
去除空白符函数
空白符主要包括\n、\r、\t、’ ‘,即:换行、回车、制表符、空格等,用到3个常用的函数;
- strip():用来去除头尾字符
- lstrip():开头字符(左边)
- rstrip():结尾字符(右边)
左右空白符
df["address"].str.strip()
0 广东省 深圳市
1 浙江省 杭州市
2 江苏省苏州市
3 福建省 泉州市
4 广东省广州市
Name: address, dtype: object
df["address"].str.strip().tolist()
['广东省 深圳市', '浙江省 杭州市', '江苏省苏州市', '福建省 泉州市', '广东省广州市']
左空白符
df["address"].str.lstrip().tolist()
['广东省 深圳市 ', '浙江省 杭州市', '江苏省苏州市 ', '福建省 泉州市', '广东省广州市']
右空白符
df["address"].str.rstrip().tolist()
[' 广东省 深圳市', '浙江省 杭州市', ' 江苏省苏州市', '福建省 泉州市', '广东省广州市']
对比Python自带函数
str.strip([chars):其中chars是可选的;
-
如果没有的话就是默认删除空白符,\n、\t、空白符等
-
如果给定的字符,当chars不为空时,函数会把chars解成一个个的字符,然后将这些字符去掉
s = " AB CD EF "
s
' AB CD EF '
下面是chars选项为空的时候:
1、删除左右两边的空白符
s.strip()
'AB CD EF'
2、删除左边的空白符
s.lstrip()
'AB CD EF '
3、删除右边的空白符
s.rstrip()
' AB CD EF'
当chars选项不为空的时候:
ss = "12AB C21D EF21"
ss
'12AB C21D EF21'
此时"12"字符串被拆解成两个字符1和2,然后单独去删除:
ss.strip("12")
'AB C21D EF'
删除左边的1或者2:
ss.lstrip("12")
'AB C21D EF21'
删除右边的1或者2
ss.rstrip("12")
'12AB C21D EF'
分割函数
split函数
Series.str.split(
pat=None, # 字符或正则表达式,默认是空白符
n=- 1, # 分割次数
expand=False, # 是否扩展
regex=None # 决定传入模式是否为正则
)
关于参数regex的解释(版本1.4.0开始出现的):
- True:默认是正则
- False:默认是普通字符
- None and pat length is 1:普通字符
- None and pat length is not 1:正则表达式
注意:当传入的是正则表达式的时候,不能设置成False
df["name"].str.split() # 默认空白符分割
0 [xiao, ming]
1 [xiao, zhang]
2 NaN
3 [sun, quan]
4 [guan, yu]
Name: name, dtype: object
df["name"].str.split(" ")
0 [xiao, ming]
1 [xiao, zhang]
2 NaN
3 [sun, quan]
4 [guan, yu]
Name: name, dtype: object
指定非空的分割符号:
df["sex"].str.split("a") # 指定分隔符
0 [m, le]
1 [Fem, le]
2 [fem, le]
3 [Fem, le]
4 [m, le]
Name: sex, dtype: object
将分割的结果进行扩展,生成的是DataFrame:
df["name"].str.split(expand=True)
| 0 | 1 | |
|---|---|---|
| 0 | xiao | ming |
| 1 | xiao | zhang |
| 2 | NaN | NaN |
| 3 | sun | quan |
| 4 | guan | yu |
通过 get 函数或者[]来访问切割后的结果:
df["name"].str.split(expand=True).get(1)
0 ming
1 zhang
2 NaN
3 quan
4 yu
Name: 1, dtype: object
df["name"].str.split(expand=True)[1]
0 ming
1 zhang
2 NaN
3 quan
4 yu
Name: 1, dtype: object
rsplit函数
df["sex"].str.rsplit("a") # 指定分隔符
0 [m, le]
1 [Fem, le]
2 [fem, le]
3 [Fem, le]
4 [m, le]
Name: sex, dtype: object
df["sex"].str.rsplit("f") # 指定分隔符
0 [male]
1 [Female]
2 [, emale]
3 [Female]
4 [male]
Name: sex, dtype: object
如何理解分割次数n
s3 = pd.Series("abcdabcab")
s3
0 abcdabcab
dtype: object
通过字符b来进行切割,默认参数下:
s3.str.rsplit("b")
0 [a, cda, ca, ]
dtype: object
切割的最大次数为2,生成3个元素:
s3.str.split("b",n=2)
0 [a, cda, cab]
dtype: object
指定切割3次后的结果:
s3.str.split("b",n=3)
0 [a, cda, ca, ]
dtype: object
最大的切割次数是3,下面切割4次和3次的效果相同:
s3.str.split("b",n=4)
0 [a, cda, ca, ]
dtype: object
n=-1表示切割的最大次数,默认情况:
s3.str.split("b",n=-1)
0 [a, cda, ca, ]
dtype: object