Pandas文本数据处理

文本数据处理

更多:Pandas

Pandas缺失值处理 介绍了 Pandas 中缺失值的处理,这一节我们来看一看如何处理 Pandas 中的文本(字符串)。

# 导入相关库
import numpy as np
import pandas as pd
为什么要用str属性

文本数据也就是我们常说的字符串,Pandas 为 Series 提供了 str 属性,通过它可以方便的对每个元素进行操作。

index = pd.Index(data=["Tom", "Bob", "Mary", "James", "Andy", "Alice"], name="name")

data = {
    "age": [18, 30, np.nan, 40, np.nan, 30],
    "city": ["Bei Jing ", "Shang Hai ", "Guang Zhou", "Shen Zhen", np.nan, " "],
    "sex": [None, "male", "female", "male", np.nan, "unknown"],
    "birth": ["2000-02-10", "1988-10-17", None, "1978-08-08", np.nan, "1988-10-17"]
}

user_info = pd.DataFrame(data=data, index=index)

# 将出生日期转为时间戳
user_info["birth"] = pd.to_datetime(user_info.birth)
user_info
agebirthcitysex
name
Tom18.02000-02-10Bei JingNone
Bob30.01988-10-17Shang Haimale
MaryNaNNaTGuang Zhoufemale
James40.01978-08-08Shen Zhenmale
AndyNaNNaTNaNNaN
Alice30.01988-10-17unknown

在之前已经了解过,在对 Series 中每个元素处理时,我们可以使用 mapapply 方法。

比如,我想要将每个城市都转为小写,可以使用如下的方式。

user_info.city.map(lambda x: x.lower())
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

 in ()
----> 1 user_info.city.map(lambda x: x.lower())


C:\soft\py3\lib\site-packages\pandas\core\series.py in map(self, arg, na_action)
   2156         else:
   2157             # arg is a function
-> 2158             new_values = map_f(values, arg)
   2159 
   2160         return self._constructor(new_values,


pandas/_libs/src\inference.pyx in pandas._libs.lib.map_infer()


 in (x)
----> 1 user_info.city.map(lambda x: x.lower())


AttributeError: 'float' object has no attribute 'lower'

What?竟然出错了,错误原因是因为 float 类型的对象没有 lower 属性。这是因为缺失值(np.nan)属于float 类型。

这时候我们的 str 属性操作来了,来看看如何使用吧。

# 将文本转为小写
user_info.city.str.lower()
name
Tom       bei jing 
Bob      shang hai 
Mary     guang zhou
James     shen zhen
Andy            NaN
Alice              
Name: city, dtype: object

可以看到,通过 str 属性来访问之后用到的方法名与 Python 内置的字符串的方法名一样。并且能够自动排除缺失值。

我们再来试试其他一些方法。例如,统计每个字符串的长度。

user_info.city.str.len()
name
Tom       9.0
Bob      10.0
Mary     10.0
James     9.0
Andy      NaN
Alice     1.0
Name: city, dtype: float64
替换和分割

使用 .srt 属性也支持替换与分割操作。

先来看下替换操作,例如:将空字符串替换成下划线。

user_info.city.str.replace(" ", "_")
name
Tom       Bei_Jing_
Bob      Shang_Hai_
Mary     Guang_Zhou
James     Shen_Zhen
Andy            NaN
Alice             _
Name: city, dtype: object

replace 方法还支持正则表达式,例如将所有开头为 S 的城市替换为空字符串。

user_info.city.str.replace("^S.*", " ")
name
Tom       Bei Jing 
Bob                
Mary     Guang Zhou
James              
Andy            NaN
Alice              
Name: city, dtype: object

再来看下分割操作,例如根据空字符串来分割某一列。

user_info.city.str.split(" ")
name
Tom       [Bei, Jing, ]
Bob      [Shang, Hai, ]
Mary      [Guang, Zhou]
James      [Shen, Zhen]
Andy                NaN
Alice              [, ]
Name: city, dtype: object

分割列表中的元素可以使用 get[] 符号进行访问:

user_info.city.str.split(" ").str.get(1)
name
Tom      Jing
Bob       Hai
Mary     Zhou
James    Zhen
Andy      NaN
Alice        
Name: city, dtype: object
user_info.city.str.split(" ").str[1]
name
Tom      Jing
Bob       Hai
Mary     Zhou
James    Zhen
Andy      NaN
Alice        
Name: city, dtype: object

设置参数 expand=True 可以轻松扩展此项以返回 DataFrame。

user_info.city.str.split(" ", expand=True)
012
name
TomBeiJing
BobShangHai
MaryGuangZhouNone
JamesShenZhenNone
AndyNaNNoneNone
AliceNone
提取子串

既然是在操作字符串,很自然,你可能会想到是否可以从一个长的字符串中提取出子串。答案是可以的。

提取第一个匹配的子串

extract 方法接受一个正则表达式并至少包含一个捕获组,指定参数 expand=True 可以保证每次都返回 DataFrame。

例如,现在想要匹配空字符串前面的所有的字母,可以使用如下操作:

user_info.city.str.extract("(\w+)\s+", expand=True)
0
name
TomBei
BobShang
MaryGuang
JamesShen
AndyNaN
AliceNaN

如果使用多个组提取正则表达式会返回一个 DataFrame,每个组只有一列。

例如,想要匹配出空字符串前面和后面的所有字母,操作如下:

user_info.city.str.extract("(\w+)\s+(\w+)", expand=True)
01
name
TomBeiJing
BobShangHai
MaryGuangZhou
JamesShenZhen
AndyNaNNaN
AliceNaNNaN
匹配所有子串

extract 只能够匹配出第一个子串,使用 extractall 可以匹配出所有的子串。

例如,将所有组的空白字符串前面的字母都匹配出来,可以如下操作。

user_info.city.str.extractall("(\w+)\s+")
0
namematch
Tom0Bei
1Jing
Bob0Shang
1Hai
Mary0Guang
James0Shen
测试是否包含子串

除了可以匹配出子串外,我们还可以使用 contains 来测试是否包含子串。例如,想要测试城市是否包含子串 “Zh”。

user_info.city.str.contains("Zh")
name
Tom      False
Bob      False
Mary      True
James     True
Andy       NaN
Alice    False
Name: city, dtype: object

当然了,正则表达式也是支持的。例如,想要测试是否是以字母 “S” 开头。

user_info.city.str.contains("^S")
name
Tom      False
Bob       True
Mary     False
James     True
Andy       NaN
Alice    False
Name: city, dtype: object
生成哑变量

这是一个神奇的功能,通过 get_dummies 方法可以将字符串转为哑变量,sep 参数是指定哑变量之间的分隔符。来看看效果吧。

user_info.city.str.get_dummies(sep=" ")
BeiGuangHaiJingShangShenZhenZhou
name
Tom10010000
Bob00101000
Mary01000001
James00000110
Andy00000000
Alice00000000

这样,它提取出了 Bei, Guang, Hai, Jing, Shang, Shen, Zhen, Zhou 这些哑变量,并对每个变量下使用 0 或 1 来表达。实际上与 One-Hot(狂热编码)是一回事。听不懂没关系,之后将机器学习相关知识时会详细介绍这里。

方法摘要

这里列出了一些常用的方法摘要。

方法描述
cat()连接字符串
split()在分隔符上分割字符串
rsplit()从字符串末尾开始分隔字符串
get()索引到每个元素(检索第i个元素)
join()使用分隔符在系列的每个元素中加入字符串
get_dummies()在分隔符上分割字符串,返回虚拟变量的DataFrame
contains()如果每个字符串都包含pattern / regex,则返回布尔数组
replace()用其他字符串替换pattern / regex的出现
repeat()重复值(s.str.repeat(3)等同于x * 3 t2 >)
pad()将空格添加到字符串的左侧,右侧或两侧
center()相当于str.center
ljust()相当于str.ljust
rjust()相当于str.rjust
zfill()等同于str.zfill
wrap()将长长的字符串拆分为长度小于给定宽度的行
slice()切分Series中的每个字符串
slice_replace()用传递的值替换每个字符串中的切片
count()计数模式的发生
startswith()相当于每个元素的str.startswith(pat)
endswith()相当于每个元素的str.endswith(pat)
findall()计算每个字符串的所有模式/正则表达式的列表
match()在每个元素上调用re.match,返回匹配的组作为列表
extract()在每个元素上调用re.search,为每个元素返回一行DataFrame,为每个正则表达式捕获组返回一列
extractall()在每个元素上调用re.findall,为每个匹配返回一行DataFrame,为每个正则表达式捕获组返回一列
len()计算字符串长度
strip()相当于str.strip
rstrip()相当于str.rstrip
lstrip()相当于str.lstrip
partition()等同于str.partition
rpartition()等同于str.rpartition
lower()相当于str.lower
upper()相当于str.upper
find()相当于str.find
rfind()相当于str.rfind
index()相当于str.index
rindex()相当于str.rindex
capitalize()相当于str.capitalize
swapcase()相当于str.swapcase
normalize()返回Unicode标准格式。相当于unicodedata.normalize
translate()等同于str.translate
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

发表评论

电子邮件地址不会被公开。 必填项已用*标注