【pandas】 文本数据

文本数据

str对象

str对象的设计意图

str对象是定义在IndexSeries上的属性,专门用于逐元素处理文本内容,其内部定义了大量方法,因此对一个序列进行文本处理,首先需要获取其str对象。在Python标准库中也有str模块,为了使用上的便利,有许多函数的用法pandas照搬了它的设计

【】索引器

对于str对象而言,可理解为其对字符串进行了序列化的操作,例如在一般的字符串中,通过[]可以取出某个位置的元素,同时也能通过切片得到子串。

string类型

pandas1.0.0版本开始,引入了string类型,其引入的动机在于:原来所有的字符串类型都会以object类型的Series进行存储,但object类型只应当存储混合类型,例如同时存储浮点、字符串、字典、列表、自定义类型等,因此字符串有必要同数值型或category一样,具有自己的数据存放类型,从而引入了string类型。

总体上说,绝大多数对于objectstring类型的序列使用str对象方法产生的结果是一致,但是在下面提到的两点上有较大差异:

string类型要求序列中至少有一个可迭代(Iterable)对象,包括但不限于字符串、字典、列表。但一般来说,当每一个序列中的值都是字符串的情况下使用str属性最佳。

因为对于一个可迭代对象,string类型的str对象和object类型的str对象返回结果可能是不同的。

正则表达式基础

一般字符的匹配

正则表达式是一种按照某种正则模式,从左到右匹配字符串中内容的一种工具。对于一般的字符而言,它可以找到其所在的位置,这里为了演示便利,使用了pythonre模块的findall函数来匹配所有出现过但不重叠的模式,第一个参数是正则表达式,第二个参数是待匹配的字符串。

re.findall(正则表达式,待匹配的字符串)

元字符基础

元字符 描述
. 匹配除换行符以外的任意字符
[ ] 字符类,匹配方括号中包含的任意字符
[^ ] 否定字符类,匹配方括号中不包含的任意字符
* 匹配前面的子表达式零次或多次
+ 匹配前面的子表达式一次或多次
? 匹配前面的子表达式零次或一次
{n,m} 花括号,匹配前面字符至少 n 次,但是不超过 m 次
(xyz) 字符组,按照确切的顺序匹配字符xyz
| 分支结构,匹配符号之前的字符或后面的字符
\ 转义符,它可以还原元字符原来的含义
^ 匹配行的开始
$ 匹配行的结束

简写字符集

此外,正则表达式中还有一类简写字符集,其等价于一组字符的集合:

简写 描述
\w 匹配所有字母、数字、下划线: [a-zA-Z0-9_]
\W 匹配非字母和数字的字符: [^\w]
\d 匹配数字: [0-9]
\D 匹配非数字: [^\d]
\s 匹配空格符: [\t\n\f\r\p{Z}]
\S 匹配非空格符: [^\s]
\B 匹配一组非空字符开头或结尾的位置,不代表具体字符

文本处理的五类操作

拆分

Series.str.split(正则表达式, n, expand)

  • n : 从左到右的最大拆分次数
  • expand:是否展开为多个列,默认False

合并

str.join表示用某个连接符把Series中的字符串列表连接起来,如果列表中出现了非字符串元素则返回缺失值

扫描二维码关注公众号,回复: 12419250 查看本文章
s = pd.Series([['a','b'], [1, 'a'], [['a', 'b'], 'c']])
s.str.join('-')
#0    a-b
#1    NaN
#2    NaN
#dtype: object

str.cat用于合并两个序列,主要参数为连接符sep、连接形式join以及缺失值替代符号na_rep,其中连接形式默认为以索引为键的左连接。

s1 = pd.Series(['a','b'])
s2 = pd.Series(['cat','dog'])
s1.str.cat(s2,sep='-')
#0    a-cat
#1    b-dog
#dtype: object

匹配

str.contains返回了每个字符串是否包含正则模式的布尔序列

str.startswithstr.endswith返回了每个字符串以给定模式为开始和结束的布尔序列,它们都不支持正则表达式:

替换

str.replacereplace并不是一个函数,在使用字符串替换时应当使用前者。

提取

提取既可以认为是一种返回具体元素(而不是布尔值或元素对应的索引位置)的匹配操作,也可以认为是一种特殊的拆分操作。前面提到的str.split例子中会把分隔符去除,这并不是用户想要的效果,这时候就可以用str.extract进行提取:

s = pd.Series(['上海市黄浦区方浜中路249号',
                '上海市宝山区密山路5号',
                '北京市昌平区北农路2号'])
pat = '(\w+市)(\w+区)(\w+路)(\d+号)'
s.str.extract(pat)

常用字符串函数

字母型函数

upper, lower, title, capitalize, swapcase这五个函数主要用于字母的大小写转化。和标准库一样。

数值型函数

pd.to_numeric方法,它虽然不是str对象上的方法,但是能够对字符格式的数值进行快速转换和筛选。其主要参数包括errorsdowncast分别代表了非数值的处理模式和转换类型。其中,对于不能转换为数值的有三种errors选项,raise, coerce, ignore分别表示直接报错、设为缺失以及保持原来的字符串。

统计型函数

countlen的作用分别是返回出现正则模式的次数和字符串的长度

格式型函数

格式型函数主要分为两类,第一种是除空型,第二种时填充型。

其中,第一类函数一共有三种,它们分别是strip, rstrip, lstrip,分别代表去除两侧空格、右侧空格和左侧空格。这些函数在数据清洗时是有用的,特别是列名含有非法空格的时候。

第二类填充型函数,pad是最灵活的,它可以选定字符串长度、填充的方向和填充内容。还有rjust, ljust, center,zfill,需要注意ljust是指右侧填充而不是左侧填充。

练习

Ex1 房屋信息数据集

现有一份房屋信息数据集如下:

df = pd.read_excel('../data/house_info.xls', usecols=['floor','year','area','price'])
df.head(3)
  1. year列改为整数年份存储。
  2. floor列替换为Level, Highest两列,其中的元素分别为string类型的层类别(高层、中层、低层)与整数类型的最高层数。
  3. 计算房屋每平米的均价avg_price,以***元/平米的格式存储到表中,其中***为整数。
## 1
df.year = pd.to_numeric(df.year.str[:4], errors='ignore').astype('Int64')
df.head()

在这里插入图片描述

## 2
import re

pat = '(?P<Level>\w层)(共(?P<Highest>\d+)层)'
df = pd.concat([df.drop(columns='floor'), df.floor.str.extract(pat)], axis=1)
df.Level = df.Level.astype('string')
df.Highest = pd.to_numeric(df.Highest).astype('Int64')
df.head()

在这里插入图片描述

## 3
area_series = pd.to_numeric(df.area.str[:-1])
price_series = pd.to_numeric(df.price.str[:-1])
df['avg_price'] = (round(price_series * 10000 / area_series, 2)).astype('string') + '元/平米'
df.head()

在这里插入图片描述

Ex2 权游剧本数据集

现有一份权力的游戏剧本数据集如下:

df = pd.read_csv('../data/script.csv')
df.head(3)
  1. 计算每一个Episode的台词条数。
  2. 以空格为单词的分割符号,请求出单句台词平均单词量最多的前五个人。
  3. 若某人的台词中含有问号,那么下一个说台词的人即为回答者。若上一人台词中含有 n n n个问号,则认为回答者回答了 n n n个问题,请求出回答最多问题的前五个人。
## 1
df = df.copy()
df.columns = df.columns.str.strip()
#进行分组求和,求出每一个Episode的台词条数
gb = df.groupby('Episode')['Sentence'].count()
gb.head(2)

在这里插入图片描述

## 2
#求出每行单词量
df['Vocabulary'] = df['Sentence'].str.split(' ').str.len()
#分组求出平均单词量
gb = df.groupby('Name')['Vocabulary'].mean()
#根据values进行排序
gb = gb.sort_values(ascending = False)
#选取前5
gb.head(5)

在这里插入图片描述

## 3
#求出回答问题的数量
df['count'] = df['Sentence'].str.count('\?')
#分组求出总回答问题数
gb = df.groupby('Name')['count'].sum()
#根据values进行排序
gb = gb.sort_values(ascending = False)
#选取前5
gb.head(5)

在这里插入图片描述

感谢 joyful pandas第八章文本数据

猜你喜欢

转载自blog.csdn.net/weixin_41545602/article/details/112299797