pandas文本处理的3大秘诀

公众号:尤而小屋
作者:Peter
编辑:Peter

大家好,我是Peter~

本文主要介绍的是通过使用Pandas中3个字符串相关函数来筛选满足需求的文本数据:

  • contains :包含某个字符
  • startswith:以字符开头
  • endswith:以字符结尾
image

模拟数据

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
image
df.dtypes  # 查看字段类型
name       object
age        object
sex        object
address    object
dtype: object

在本次模拟的数据中,有4个特点:

  1. name字段:存在缺失值np.nan,且Xiao和xiao存在大小写之分
  2. age:年龄字段,正常应该是数值型,模拟的数据是字符类型object
  3. sex:也存在F和f的大小写之分
  4. address:正常写法

数据类型转换

我们将age字段的字符类型型转成数值型

df["age"] = df["age"].astype(float)
df

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

生成的数据如下,似乎和原始数据没有区别;但是我们查看属性字段的数据类型就会看到区别:

image
df.dtypes
name        object
age        float64  
sex         object
address     object
dtype: object

age字段已经转成了float64位的数值型。

contains

contains是用于Series数据的函数,基本语法如下:

Series.str.contains(
    pat, 
    case=True, 
    flags=0, 
    na=None, 
    regex=True
)
  • pat:传入的字符或者正则表达式
  • case:是否区分大小写(对大小写敏感)
  • flags:正则标志位,比如:re.IGNORECASE,表示忽略大小写
  • na:可选项,标量类型;对原数据中的缺失值处理,如果是object-dtype, 使用numpy.nan 代替;如果是StringDtype, 用pandas.NA
  • regex:布尔值;True:传入的pat看做是正则表达式,False:看做是正常的字符类型的表达式

默认情况

# 例子1:筛选包含xiao的数据

df["name"].str.contains("xiao")
0     True
1    False
2      NaN
3    False
4    False
Name: name, dtype: object

当属性中存在缺失值的时候,需要带上na参数:

缺失值处理

# 例子2:参数na使用

df[df["name"].str.contains("xiao",na=False)]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
</tbody>
</table>

</div>

如果不带上则会报错:

df[df["name"].str.contains("xiao")]
image

忽略大小写

# 例子3:case使用

df["name"].str.contains("xiao",case=False)
0     True
1     True
2      NaN
3    False
4    False
Name: name, dtype: object

上面的结果直接忽略了大小写,可以看到出现了两个True:也就是xiao和Xiao的数据都被筛选出来:

df[df["name"].str.contains("xiao",case=False, na=False)]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
</tbody>
</table>

</div>

忽略大小写和缺失值

# 例子4:忽略大小写和缺失值
df[df["sex"].str.contains("f",case=False, na=False)]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
<tr>
<th>2</th>
<td>NaN</td>
<td>20.0</td>
<td>female</td>
<td>江苏省苏州市</td>
</tr>
<tr>
<th>3</th>
<td>sun quan</td>
<td>34.0</td>
<td>Female</td>
<td>福建省泉州市</td>
</tr>
</tbody>
</table>

</div>

正则表达式使用

# 例子5:正则表达式使用

df["address"].str.contains("^广")
0     True
1    False
2    False
3    False
4     True
Name: address, dtype: bool

其中^表示开始的符号,即:以广开头的数据

df[df["address"].str.contains("^广")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>4</th>
<td>guan yu</td>
<td>39.0</td>
<td>male</td>
<td>广东省广州市</td>
</tr>
</tbody>
</table>

</div>

正则表达式中的$表示结尾的符号;下面是筛选以结尾的数据:

df[df["address"].str.contains("市$")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
<tr>
<th>2</th>
<td>NaN</td>
<td>20.0</td>
<td>female</td>
<td>江苏省苏州市</td>
</tr>
<tr>
<th>3</th>
<td>sun quan</td>
<td>34.0</td>
<td>Female</td>
<td>福建省泉州市</td>
</tr>
<tr>
<th>4</th>
<td>guan yu</td>
<td>39.0</td>
<td>male</td>
<td>广东省广州市</td>
</tr>
</tbody>
</table>

</div>

在下面的正则表达式例子中,会在深苏泉中任意选择一个,然后包含这个字符的数据:

df[df["address"].str.contains("[深苏泉]")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>2</th>
<td>NaN</td>
<td>20.0</td>
<td>female</td>
<td>江苏省苏州市</td>
</tr>
<tr>
<th>3</th>
<td>sun quan</td>
<td>34.0</td>
<td>Female</td>
<td>福建省泉州市</td>
</tr>
</tbody>
</table>

</div>

startswith

startswith的语法相对简单:

Series.str.startswith(pat, na=None)
  • pat:表示一个字符;注意:不接受正则表达式
  • na:表示对缺失值的处理;na=False表示忽略缺失值

pat参数

指定一个字符;不接受正则表达式

df["address"].str.startswith("广")
0     True
1    False
2    False
3    False
4     True
Name: address, dtype: bool
df[df["address"].str.startswith("广")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>4</th>
<td>guan yu</td>
<td>39.0</td>
<td>male</td>
<td>广东省广州市</td>
</tr>
</tbody>
</table>

</div>

这种写法和正则表达式的以某个字符开头是同样的效果:

df[df["address"].str.contains("^广")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>4</th>
<td>guan yu</td>
<td>39.0</td>
<td>male</td>
<td>广东省广州市</td>
</tr>
</tbody>
</table>

</div>

自动区分大小写

startswith方法是自动区分大小写的:

df[df["sex"].str.startswith("f")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>2</th>
<td>NaN</td>
<td>20.0</td>
<td>female</td>
<td>江苏省苏州市</td>
</tr>
</tbody>
</table>

</div>

df[df["sex"].str.startswith("F")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
<tr>
<th>3</th>
<td>sun quan</td>
<td>34.0</td>
<td>Female</td>
<td>福建省泉州市</td>
</tr>
</tbody>
</table>

</div>

缺失值处理

df["name"].str.startswith("xiao")
0     True
1    False
2      NaN
3    False
4    False
Name: name, dtype: object
df[df["name"].str.startswith("xiao",na=False)]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
</tbody>
</table>

</div>

endswith

指定以某个字符结尾,语法为:

Series.str.endswith(pat, na=None)
  • pat:表示一个字符;注意:不接受正则表达式
  • na:表示对缺失值的处理;na=False表示忽略缺失值

pat参数

# 以市结尾

df[df["address"].str.endswith("市")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
<tr>
<th>2</th>
<td>NaN</td>
<td>20.0</td>
<td>female</td>
<td>江苏省苏州市</td>
</tr>
<tr>
<th>3</th>
<td>sun quan</td>
<td>34.0</td>
<td>Female</td>
<td>福建省泉州市</td>
</tr>
<tr>
<th>4</th>
<td>guan yu</td>
<td>39.0</td>
<td>male</td>
<td>广东省广州市</td>
</tr>
</tbody>
</table>

</div>

# 正则的写法:contains方法

df[df["address"].str.contains("市$")]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
<tr>
<th>2</th>
<td>NaN</td>
<td>20.0</td>
<td>female</td>
<td>江苏省苏州市</td>
</tr>
<tr>
<th>3</th>
<td>sun quan</td>
<td>34.0</td>
<td>Female</td>
<td>福建省泉州市</td>
</tr>
<tr>
<th>4</th>
<td>guan yu</td>
<td>39.0</td>
<td>male</td>
<td>广东省广州市</td>
</tr>
</tbody>
</table>

</div>

缺失值处理

df["name"].str.endswith("g")
0     True
1     True
2      NaN
3    False
4    False
Name: name, dtype: object
df[df["name"].str.endswith("g",na=False)]

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>

<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>name</th>
<th>age</th>
<th>sex</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>xiao ming</td>
<td>22.0</td>
<td>male</td>
<td>广东省深圳市</td>
</tr>
<tr>
<th>1</th>
<td>Xiao zhang</td>
<td>19.0</td>
<td>Female</td>
<td>浙江省杭州市</td>
</tr>
</tbody>
</table>

</div>

# 不加na参数则报错
df[df["name"].str.endswith("g")]
image

报错的原因很明显:就是因为name字段下面存在缺失值。当使用了na参数就可以解决

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容