Pandas文本处理大全的3大秘诀
本文介绍Pandas中针对文本数据处理的方法。文本数据也就是我们常说的字符串,Pandas 为 Series 提供了 str 属性,通过它可以方便的对每个元素进行操作。
首先需要清楚的是:Python中原生的字符串操作的相关的函数也是适用的。
代码语言:javascript复制import pandas as pd
import numpy as np
模拟数据
代码语言:javascript复制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
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
name | age | sex | address | |
---|---|---|---|---|
0 | xiao ming | 22 | male | 广东省 深圳市 |
1 | xiao zhang | 19 | Female | 浙江省 杭州市 |
2 | NaN | 20 | female | 江苏省苏州市 |
3 | sun quan | 34 | Female | 福建省 泉州市 |
4 | guan yu | 39 | male | 广东省广州市 |
df.dtypes
代码语言:javascript复制name object
age int64
sex object
address object
dtype: object
字母转换函数
在Python原生的字符串转换中有upper、lower、title等函数和字母转换相关
upper
将字母全部转成大写的形式
代码语言:javascript复制df["sex"].str.upper()
代码语言:javascript复制0 MALE
1 FEMALE
2 FEMALE
3 FEMALE
4 MALE
Name: sex, dtype: object
lower
将字母全部转成小写形式
代码语言:javascript复制df["sex"].str.lower()
代码语言:javascript复制0 male
1 female
2 female
3 female
4 male
Name: sex, dtype: object
capitalize
第一个单词的首字母大写
代码语言:javascript复制df["name"].str.capitalize()
代码语言:javascript复制0 Xiao ming
1 Xiao zhang
2 NaN
3 Sun quan
4 Guan yu
Name: name, dtype: object
title
每个单词的首字母大写;注意和capitalize的区别:
代码语言:javascript复制df["name"].str.title()
代码语言:javascript复制0 Xiao Ming
1 Xiao Zhang
2 NaN
3 Sun Quan
4 Guan Yu
Name: name, dtype: object
swapcase
大小写互换:小写换成大写,反之,大写换成小写
代码语言:javascript复制df["name"].str.swapcase()
原来的全部是小写,下面结果全部变成了大写:
代码语言:javascript复制0 XIAO MING
1 XIAO ZHANG
2 NaN
3 SUN QUAN
4 GUAN YU
Name: name, dtype: object
代码语言:javascript复制df["sex"].str.swapcase()
代码语言:javascript复制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()
代码语言:javascript复制0 male
1 female
2 female
3 female
4 male
Name: sex, dtype: object
代码语言:javascript复制df["sex"].str.casefold()
代码语言:javascript复制0 male
1 female
2 female
3 female
4 male
Name: sex, dtype: object
但是其它一些语言里面存在小写的情况,lower()
函数就不能处理。下面我们用德语中’ß’来区分二者,真实小写是’ss’:
s = 'ß'
s.lower()
代码语言:javascript复制'ß'
使用casefold函数能够实现:
代码语言:javascript复制s.casefold()
代码语言:javascript复制'ss'
在对 Series 中每个元素处理时,我们可以使用Pandas中内置的 map 或 apply 方法
代码语言:javascript复制df["name"].apply(lambda x: x.upper())
# 结果
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-14-8aacba359806> in <module>
----> 1 df["name"].apply(lambda x: x.upper())
/Applications/downloads/anaconda/anaconda3/lib/python3.7/site-packages/pandas/core/series.py in apply(self, func, convert_dtype, args, **kwds)
4136 else:
4137 values = self.astype(object)._values
-> 4138 mapped = lib.map_infer(values, f, convert=convert_dtype)
4139
4140 if len(mapped) and isinstance(mapped[0], Series):
pandas/_libs/lib.pyx in pandas._libs.lib.map_infer()
<ipython-input-14-8aacba359806> in <lambda>(x)
----> 1 df["name"].apply(lambda x: x.upper())
AttributeError: 'float' object has no attribute 'upper'
可以看到出现了报错:float类型的数据是没有upper属性的。这是因为数据中出现了NaN,NaN在Pandas中是被当做float类型。
下面使用upper方法来实现转换:当使用str.upper进行转换的时候能够自动排除缺失值的数据。
代码语言:javascript复制df["name"].str.upper() # 写法1
df.name.str.upper() # 写法2
代码语言:javascript复制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():结尾字符(右边)
左右空白符
代码语言:javascript复制df["address"].str.strip()
代码语言:javascript复制0 广东省 深圳市
1 浙江省 杭州市
2 江苏省苏州市
3 福建省 泉州市
4 广东省广州市
Name: address, dtype: object
代码语言:javascript复制df["address"].str.strip().tolist()
代码语言:javascript复制['广东省 深圳市', '浙江省 杭州市', '江苏省苏州市', '福建省 泉州市', '广东省广州市']
左空白符
代码语言:javascript复制df["address"].str.lstrip().tolist()
代码语言:javascript复制['广东省 深圳市 ', '浙江省 杭州市', '江苏省苏州市 ', '福建省 泉州市', '广东省广州市']
右空白符
代码语言:javascript复制df["address"].str.rstrip().tolist()
代码语言:javascript复制[' 广东省 深圳市', '浙江省 杭州市', ' 江苏省苏州市', '福建省 泉州市', '广东省广州市']
对比Python自带函数
str.strip([chars)
:其中chars是可选的;
- 如果没有的话就是默认删除空白符,n、t、空白符等
- 如果给定的字符,当chars不为空时,函数会把chars解成一个个的字符,然后将这些字符去掉
s = " AB CD EF "
s
代码语言:javascript复制' AB CD EF '
下面是chars选项为空的时候:
1、删除左右两边的空白符
代码语言:javascript复制s.strip()
代码语言:javascript复制'AB CD EF'
2、删除左边的空白符
代码语言:javascript复制s.lstrip()
代码语言:javascript复制'AB CD EF '
3、删除右边的空白符
代码语言:javascript复制s.rstrip()
代码语言:javascript复制' AB CD EF'
当chars选项不为空的时候:
代码语言:javascript复制ss = "12AB C21D EF21"
ss
代码语言:javascript复制'12AB C21D EF21'
此时"12"字符串被拆解成两个字符1
和2
,然后单独去删除:
ss.strip("12")
代码语言:javascript复制'AB C21D EF'
删除左边的1或者2:
代码语言:javascript复制ss.lstrip("12")
代码语言:javascript复制'AB C21D EF21'
删除右边的1或者2
代码语言:javascript复制ss.rstrip("12")
代码语言:javascript复制'12AB C21D EF'
分割函数
split函数
代码语言:javascript复制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
代码语言:javascript复制df["name"].str.split() # 默认空白符分割
代码语言:javascript复制0 [xiao, ming]
1 [xiao, zhang]
2 NaN
3 [sun, quan]
4 [guan, yu]
Name: name, dtype: object
代码语言:javascript复制df["name"].str.split(" ")
代码语言:javascript复制0 [xiao, ming]
1 [xiao, zhang]
2 NaN
3 [sun, quan]
4 [guan, yu]
Name: name, dtype: object
指定非空的分割符号:
代码语言:javascript复制df["sex"].str.split("a") # 指定分隔符
代码语言:javascript复制0 [m, le]
1 [Fem, le]
2 [fem, le]
3 [Fem, le]
4 [m, le]
Name: sex, dtype: object
将分割的结果进行扩展,生成的是DataFrame:
代码语言:javascript复制df["name"].str.split(expand=True)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
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)
代码语言:javascript复制0 ming
1 zhang
2 NaN
3 quan
4 yu
Name: 1, dtype: object
代码语言:javascript复制df["name"].str.split(expand=True)[1]
代码语言:javascript复制0 ming
1 zhang
2 NaN
3 quan
4 yu
Name: 1, dtype: object
rsplit函数
代码语言:javascript复制df["sex"].str.rsplit("a") # 指定分隔符
代码语言:javascript复制0 [m, le]
1 [Fem, le]
2 [fem, le]
3 [Fem, le]
4 [m, le]
Name: sex, dtype: object
代码语言:javascript复制df["sex"].str.rsplit("f") # 指定分隔符
代码语言:javascript复制0 [male]
1 [Female]
2 [, emale]
3 [Female]
4 [male]
Name: sex, dtype: object
如何理解分割次数n
代码语言:javascript复制s3 = pd.Series("abcdabcab")
s3
代码语言:javascript复制0 abcdabcab
dtype: object
通过字符b来进行切割,默认参数下:
代码语言:javascript复制s3.str.rsplit("b")
代码语言:javascript复制0 [a, cda, ca, ]
dtype: object
切割的最大次数为2,生成3个元素:
代码语言:javascript复制s3.str.split("b",n=2)
代码语言:javascript复制0 [a, cda, cab]
dtype: object
指定切割3次后的结果:
代码语言:javascript复制s3.str.split("b",n=3)
代码语言:javascript复制0 [a, cda, ca, ]
dtype: object
最大的切割次数是3,下面切割4次和3次的效果相同:
代码语言:javascript复制s3.str.split("b",n=4)
代码语言:javascript复制0 [a, cda, ca, ]
dtype: object
n=-1表示切割的最大次数,默认情况:
代码语言:javascript复制s3.str.split("b",n=-1)
代码语言:javascript复制0 [a, cda, ca, ]
dtype: object