↑↑↑关注后"星标"Datawhale
每日干货 & 每月组队学习,不错过
Datawhale干货
作者:耿远昊,Datawhale成员,华东师范大学
文本数据是指不能参与算术运算的任何字符,也称为字符型数据。如英文字母、汉字、不作为数值使用的数字(以单引号开头)和其他可输入的字符。文本数据具有数据维度高、数据量大且语义复杂等特点,是一种较为复杂的数据类型。今天,我们就来一起看看如何使用Pandas对文本数据进行数据处理。 本文目录
1. string类型的性质 1.1. string与object的区别 1.2. string类型的转换 2. 拆分与拼接 2.1. str.split方法 2.2. str.cat方法 3. 替换 3.1. str.replace的常见用法 3.2. 子组与函数替换 3.3. 关于str.replace的注意事项 4. 字串匹配与提取 4.1. str.extract方法 4.2. str.extractall方法 4.3. str.contains和str.match 5. 常用字符串方法 5.1. 过滤型方法 5.2. isnumeric方法 6. 问题及练习 6.1. 问题 6.2. 练习
首先,导入需要使用的包
import pandas as pd
import numpy as np
#pd.Series([1,'1.']).astype('string') #报错
#pd.Series([1,2]).astype('string') #报错
#pd.Series([True,False]).astype('string') #报错
pd.Series([1,'1.']).astype('str').astype('string')
0 1
1 1
dtype: string
pd.Series([1,2]).astype('str').astype('string')
0 1
1 2
dtype: string
pd.Series([True,False]).astype('str').astype('string')
0 True
1 False
dtype: string
s = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'], dtype="string")
s
0 a_b_c
1 c_d_e
2
3 f_g_h
dtype: string
s.str.split('_')
0 [a, b, c]
1 [c, d, e]
2
3 [f, g, h]
dtype: object
s.str.split('_').str[1]
0 b
1 d
2
3 g
dtype: object
pd.Series(['a_b_c', ['a','b','c']], dtype="object").str[1]
#第一个元素先转为['a','_','b','_','c']
0 _
1 b
dtype: object
s.str.split('_',expand=True)
s.str.split('_',n=1)
0 [a, b_c]
1 [c, d_e]
2
3 [f, g_h]
dtype: object
s.str.split('_',expand=True,n=1)
2.2 str.cat方法
s = pd.Series(['ab',None,'d'],dtype='string')
s
0 ab
1
2 d
dtype: string
s.str.cat()
'abd'
s.str.cat(sep=',')
'ab,d'
s.str.cat(sep=',',na_rep='*')
'ab,*,d'
s2 = pd.Series(['24',None,None],dtype='string')
s2
0 24
1
2
dtype: string
s.str.cat(s2)
0 ab24
1
2
dtype: string
s.str.cat(s2,sep=',',na_rep='*')
0 ab,24
1 *,*
2 d,*
dtype: string
s.str.cat(pd.DataFrame({0:['1','3','5'],1:['5','b',None]},dtype='string'),na_rep='*')
0 ab15
1 *3b
2 d5*
dtype: string
s.str.cat([s+'0',s*2])
0 abab0abab
1
2 dd0dd
dtype: string
s2 = pd.Series(list('abc'),index=[1,2,3],dtype='string')
s2
1 a
2 b
3 c
dtype: string
s.str.cat(s2,na_rep='*')
0 ab*
1 *a
2 db
dtype: string
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca','', np.nan, 'CABA', 'dog', 'cat'],dtype="string")
s
0 A
1 B
2 C
3 Aaba
4 Baca
5
6
7 CABA
8 dog
9 cat
dtype: string
s.str.replace(r'^[AB]','***')
0 ***
1 ***
2 C
3 ***aba
4 ***aca
5
6
7 CABA
8 dog
9 cat
dtype: string
s.str.replace(r'([ABC])(\w+)',lambda x:x.group(2)[1:]+'*')
0 A
1 B
2 C
3 ba*
4 ca*
5
6
7 BA*
8 dog
9 cat
dtype: string
s.str.replace(r'(?P[ABC])(?P\w+)',lambda x:x.group('two')[1:]+'*')
0 A
1 B
2 C
3 ba*
4 ca*
5
6
7 BA*
8 dog
9 cat
dtype: string
#pd.Series(['A','B'],dtype='string').str.replace(r'[A]',pd.NA) #报错
#pd.Series(['A','B'],dtype='O').str.replace(r'[A]',pd.NA) #报错
pd.Series(['A','B'],dtype='string').astype('O').replace(r'[A]',pd.NA,regex=True).astype('string')
0
1 B
dtype: string
pd.Series(['A','B'],dtype='string').replace(r'[A]','C',regex=True)
0 A
1 B
dtype: string
pd.Series(['A','B'],dtype='O').replace(r'[A]','C',regex=True)
0 C
1 B
dtype: object
#pd.Series(['A',np.nan],dtype='string').replace('A','B') #报错
pd.Series(['A',np.nan],dtype='string').str.replace('A','B')
0 B
1
dtype: string
pd.Series(['10-87', '10-88', '10-89'],dtype="string").str.extract(r'([\d]{2})-([\d]{2})')
使用子组名作为列名
pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P[\d]{2})-(?P[\d]{2})')
利用?正则标记选择部分提取
pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P[\d]{2})?-(?P[\d]{2})')
pd.Series(['10-87', '10-88', '10-'],dtype="string").str.extract(r'(?P[\d]{2})-(?P[\d]{2})?')
(b)expand参数(默认为True)
s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
s.index
Index(['A11', 'B22', 'C33'], dtype='object')
s.str.extract(r'([\w])')
s.str.extract(r'([\w])',expand=False)
A11 a
B22 b
C33 c
dtype: string
s.index.str.extract(r'([\w])')
s.index.str.extract(r'([\w])',expand=False)
Index(['A', 'B', 'C'], dtype='object')
s.index.str.extract(r'([\w])([\d])')
#s.index.str.extract(r'([\w])([\d])',expand=False) #报错
s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"],dtype="string")
two_groups = '(?P[a-z])(?P[0-9])'
s.str.extract(two_groups, expand=True)
s.str.extractall(two_groups)
s['A']='a1'
s.str.extractall(two_groups)
如果想查看第i层匹配,可使用xs方法
s = pd.Series(["a1a2", "b1b2", "c1c2"], index=["A", "B", "C"],dtype="string")
s.str.extractall(two_groups).xs(1,level='match')
4.3 str.contains和str.match
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains(r'[0-9][a-z]')
0 False
1
2 True
3 True
4 True
dtype: boolean
pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains('a', na=False)
0 False
1 False
2 True
3 False
4 False
dtype: boolean
pd.Series(['1', None, '3a_', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
0 False
1 False
2 True
3 True
4 False
dtype: boolean
pd.Series(['1', None, '_3a', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
0 False
1 False
2 False
3 True
4 False
dtype: boolean
pd.Series(list('abc'),index=[' space1 ','space2 ',' space3'],dtype="string").index.str.strip()
Index(['space1', 'space2', 'space3'], dtype='object')
pd.Series('A',dtype="string").str.lower()
0 a
dtype: string
pd.Series('a',dtype="string").str.upper()
0 A
dtype: string
pd.Series('abCD',dtype="string").str.swapcase()
0 ABcd
dtype: string
pd.Series('abCD',dtype="string").str.capitalize()
0 Abcd
dtype: string
pd.Series(['1.2','1','-0.3','a',np.nan],dtype="string").str.isnumeric()
0 False
1 True
2 False
3 False
4
dtype: boolean
# 方法一
> ex1_ori = pd.read_csv('data/String_data_one.csv',index_col='人员编号')
> ex1_ori.head()
姓名 国籍 性别 出生年 出生月 出生日
人员编号
1 aesfd 2 男 1942 8 10
2 fasefa 5 女 1985 10 4
3 aeagd 4 女 1946 10 15
4 aef 4 男 1999 5 13
5 eaf 1 女 2010 6 24
> ex1 = ex1_ori.copy()
> ex1['冒号'] = ':'
> ex1['逗号'] = ','
> ex1['国人'] = '国人'
> ex1['性别2'] = '性别'
> ex1['生于'] = '生于'
> ex1['年'] = '年'
> ex1['月'] = '月'
> ex1['日'] = '日'
> ID = ex1['姓名'].str.cat([ex1['冒号'],
ex1['国籍'].astype('str'),
ex1['国人'],
ex1['逗号'],
ex1['性别2'],
ex1['性别'],
ex1['逗号'],
ex1['生于'],
ex1['出生年'].astype('str'),
ex1['年'],
ex1['出生月'].astype('str'),
ex1['月'],
ex1['出生日'].astype('str'),
ex1['日']
])
> ex1_ori['ID'] = ID
> ex1_ori
姓名 国籍 性别 出生年 出生月 出生日 ID
人员编号
1 aesfd 2 男 1942 8 10 aesfd:2国人,性别男,生于1942年8月10日
2 fasefa 5 女 1985 10 4 fasefa:5国人,性别女,生于1985年10月4日
3 aeagd 4 女 1946 10 15 aeagd:4国人,性别女,生于1946年10月15日
4 aef 4 男 1999 5 13 aef:4国人,性别男,生于1999年5月13日
5 eaf 1 女 2010 6 24 eaf:1国人,性别女,生于2010年6月24日
# 参考答案
> dic_year = {i[0]:i[1] for i in zip(list('零一二三四五六七八九'),list('0123456789'))}
> dic_two = {i[0]:i[1] for i in zip(list('十一二三四五六七八九'),list('0123456789'))}
> dic_one = {'十':'1','二十':'2','三十':'3',None:''}
> df_res = df_new['ID'].str.extract(r'(?P<姓名>[a-zA-Z]+):(?P<国籍>[\d])国人,性别(?P<性别>[\w]),生于(?P<出生年>[\w]{4})年(?P<出生月>[\w]+)月(?P<出生日>[\w]+)日')
> df_res['出生年'] = df_res['出生年'].str.replace(r'(\w)+',lambda x:''.join([dic_year[x.group(0)[i]] for i in range(4)]))
> df_res['出生月'] = df_res['出生月'].str.replace(r'(?P\w?十)?(?P[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'0','10')
> df_res['出生日'] = df_res['出生日'].str.replace(r'(?P\w?十)?(?P[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'^0','10')
> df_res.head()
姓名 国籍 性别 出生年 出生月 出生日
人员编号
1 aesfd 2 男 1942 8 10
2 fasefa 5 女 1985 10 4
3 aeagd 4 女 1946 10 15
4 aef 4 男 1999 5 13
5 eaf 1 女 2010 6 24
【练习二】 现有一份半虚拟的数据集,第一列包含了新型冠状病毒的一些新闻标题,请解决以下问题:
ex2.col2.str.rstrip('-`').str.lstrip('/').astype(float).mean()
-0.984
ex2.columns = ex2.columns.str.strip(' ')
## !!!用于寻找脏数据
def is_number(x):
try:
float(x)
return True
except (SyntaxError, ValueError) as e:
return False
ex2[~ex2.col3.map(is_number)]
ex2.col3.str.replace(r'[`\\{]', '').astype(float).mean()
24.707484999999988
本文电子版 后台回复 文本数据 获取
“感谢你的在看,点赞,分享三连↓