Pandas处理文本的3大秘诀

2023-08-23 16:29:23 浏览数 (2)

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

广东省广州市

代码语言:javascript复制
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()相同效果

代码语言:javascript复制
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’:

代码语言:javascript复制
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解成一个个的字符,然后将这些字符去掉
代码语言:javascript复制
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"字符串被拆解成两个字符12,然后单独去删除:

代码语言:javascript复制
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 函数或者[]来访问切割后的结果:

代码语言:javascript复制
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

0 人点赞