从文件中读取数据,并使用 Pandas 的基本数据结构(Series 和 DataFrame)进行数据简单分析和处理,最后将新的数据结果保存到文件里,这就是基本的 Pandas 操作。
1 | import pandas as pd |
读取数据
最常见的文件主要是csv、excel 和 txt,所以我们重点介绍这三种文件的读取函数:
1 | df_table = pd.read_table('./data/my_table.txt', header=None, sep='\|', engine='python') |
这里有一些公共参数,header=None 表示第一行不是表头,index_col 表示把指定的列按级作为索引,parse_dates 表示将指定列解析为时间,nrows 表示读取多少行数据。对于读取 txt 文件,可能会有比较灵活的分隔符,我们可以通过 sep 参数来指定,对于与正则冲突的特殊符号需要进行转义,并指明引擎为 python。
数据写入
写入数据是通过对内置数据结构直接调用 to_csv 等方法,通常对于没有意义的(只是用来分析数据用的)索引我们会将 index 参数设置为 False,将其在保存时忽略掉。
1 | df_csv.to_csv('data/my_csv_saved.csv', index=False) |
如果想要把表格快速转换为 markdown 和 latex 语言,可以使用 to_markdown 和 to_latex 函数,此处需要安装 tabulate 包。
基本数据结构
Pandas 具有两种基本的数据结构:一维的 Series 和 二维的 DataFrame。
- Series 一般由四个部分组成,分别是序列的值 data 、索引 index 、存储类型 dtype 、序列的名字 name 。其中,索引也可以指定它的名字,默认为空
1
2
3
4s = pd.Series(data = [100, 'a', {'dic1':5}],
index = pd.Index(['id1', 20, 'third'], name='my_idx'),
dtype = 'object',
name = 'my_name') - DataFrame 在 Series 的基础上增加了列索引 columns,一个 DataFrame 由二维的 data 与行列索引来构造
1
2
3df = pd.DataFrame(data = {'col_0': [1,2,3], 'col_1':list('abc'),
'col_2': [1.2, 2.2, 3.2]},
index = ['row_%d'%i for i in range(3)])
上述的这些属性,可以通过 . 的方式来获取:
1 | print(s.values) |
另外,Series 可以使用索引取出对应的元素值。DataFrame 可以使用列索引取出相应的一个或多个列组成的表。
基本函数
我们读取一份包含了四所学校学生的体侧信息的数据,这些数据包括学校、年级、姓名、性别、身高、体重、是否为转系生、体测场次、测试时间、1000 米成绩等信息,以此作为数据来讲解 DataFrame 的基础操作。
1 | df = pd.read_csv('./data/learn_pandas.csv') |
简单总结一下,Pandas 中对于基本数据结构的内置函数包括了汇总、特征统计、唯一值、替换、排序,以及提供了 apply 函数迭代调用自定义的操作。
窗口对象
Pandas 中有 3 类窗口,分别是滑动窗口 rolling 、扩张窗口 expanding 以及指数加权窗口 ewm。得到窗口对象后,可以在指定窗口大小的数据上进行计算操作。
我们首先重点介绍一下滑动窗口,对一个序列使用 .rolling( ) 函数即可得到滑窗对象,其最重要的参数为窗口大小window。在得到了滑窗对象后,能够使用相应的聚合函数进行计算,计算则以窗口包含的数据为作用域。
1 | s = pd.Series([1, 2, 3, 4, 5]) |
shift(平移), diff(后减前的差), pct_change(后减前再除以前==“每日涨跌幅”) 是一组类滑窗函数,它们的公共参数为 periods=n ,默认为 1,分别表示取向前第 n 个元素的值、与向前第 n 个元素做差(与 Numpy 中不同,后者表示 n 阶差分)、与向前第 n 个元素相比计算增长率。这里的 n 可以为负,表示反方向的类似操作。
1 | s = pd.Series([1, 3, 6, 10, 15]) |
之所以将其视作类滑窗函数的原因是,它们的功能可以用窗口大小为 n+1 的 rolling 方法等价代替:
1 | s.rolling(3).apply(lambda x:list(x)[0]) # s.shift(2) |
扩张窗口又称累计窗口,可以理解为一个动态长度的窗口,其窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上。具体地说,设序列为 a1, a2, a3, a4,则其每个位置对应的窗口即 [a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。在上述两种窗口对象分组中的所有数值,计算的权重都是一样的,指数加权就是我们对分组中的数据给予不同的权重用于后边的计算中。
1 | s = pd.Series([1, 3, 6, 10]) |
我们简单解释一下指数加权滑动函数中的几个参数,指数加权滑动的移动窗口计算公式为:
ˆyt+1=αyt+(1−α)ˆyt其中α是平滑因子;如果根据跨度进行衰减,则α=2span+1。如果根据质心指定衰减,则α=2com+1。如果根据半衰期进行衰减,则α=1−explog(0.5)halflife。
内置对象
str对象
当一个 Pandas 序列 s 是字符串时,可以通过 s.str 获取其内置的字符串对象,Pandas 为 str 对象提供了许多操作函数,其中大量操作与 Python 本身的 str 对象的方法具有相同的用法,包括正则表达式。调用 s.str 对象的方法可以直接在整个序列上完成对字符串的操作。
1 | s = pd.Series(['a', 'bc', 'def']) |
当然,Pandas 还提供了许多 Python str 对象不具备的功能函数,如 s.str.extract() 用以提取满足特定正则的匹配结果等。
cat对象
在 Pandas 中提供了 category 类型,使用户能够处理分类类型的变量,将一个普通序列转换成分类变量可以使用 astype 方法。在一个分类类型的 Series 中定义了 cat 对象,对于一个具体的分类,有两个组成部分,其一为类别的本身,它以 Index 类型存储,其二为是否有序,它们都可以通过 cat 的属性被访问。
1 | df = pd.read_csv('data/learn_pandas.csv', |
常用的 cat 对象操作包括对分类类型的增删改查,以及构建顺序,有序类别和无序类别可以通过 as_unordered 和 reorder_categories 互相转化。
时序对象
当 Pandas 的某一列数据是时间格式串,该列就可以转换为时序对象,时序对象是一个复杂的概念,其中包括了时间戳、时间差、时间段、时间偏置等概念。对应的 Pandas 内置对象也有多种(s.dt 对象、pd.offsets.*中的 offset 对象等),我们在后面的《Pandas时序数据》中详细展开介绍。