数据控制方法

多数情况下,对于采样的原始数据,需要进行变化、分组、排序等多种操作,来获得符合要求的采样数据。针对对原始采样数据的整理需求,Pandas也提供了一系列方法来实现。以下同样以DataFrame为主列举常用的方法。

变换函数

变换函数有管道函数.pipe()、行列变换函数.apply()和元素变换函数.applymap()三个。

.pipe()可以通过给定一个变换函数和一定数量的参数作为变换函数的参数来执行自定义变换操作,这个变换操作是针对整个DataFrame进行的。自定义的变换函数将被应用于DataFrame的每一个元素上。.pipe()函数所接收的第一个参数是自定义的变换函数,其后的参数是自定义变换函数所需的除第一个参数以外的剩余参数。.pipe()会将DataFrame中的元素作为自定义变换函数的第一个参数传递给变换函数,并使用变换函数的返回值替换相应位置的元素,并最终更新DataFrame中的全部元素。

.apply()可以沿DataFrame的任意轴上执行自定义变换函数,默认操作是按列执行,可以通过指定axis参数为1来指定按行执行。.apply()的使用与.pipe()类似,可以仿照使用。

不是所有的自定义变换函数都能够使用.pipe()应用于DataFrame的每一个元素,除了.pipe()之外,Pandas还提供了.applymap()来对DataFrame中的每一个元素应用普通变换函数,针对Series中的元素是使用.map().applymap()接受任何Python函数,并返回单个值。

迭代

DataFrameSeries都是支持迭代的。对于Series来说,迭代将直接输出其索引标签,而迭代DataFrame则较为复杂。

直接使用for...in...DataFrame进行迭代,将会从DataFrame中取得其全部列名。如果需要遍历DataFrame中的行,则需要使用以下函数。

  • .iteritems(),迭代键值对,格式为(key, value)
  • .iterrows(),将行迭代为键值对,格式为(key, Series)
  • .itertuples(),使用命名元组的形式迭代行。

排序

Pandas有两种排序方式,一种是按标签排序,一种是按照实际值排序。

使用.sort_index()可以按照标签进行排序,默认情况下将按照升序对行标签进行排序操作。可以通过指定axis参数来变更排序轴,ascending参数(可取True或者False)来变更排序方向。

而使用.sort_values()可以按照实际值来进行排序。.sort_values()可以接受by参数来指定参加排序的列,kind参数来指定排序算法。由于Mergesort是Pandas中比较稳定的排序算法,所以一般情况下不必特殊指定算法。

窗口

窗口(Window)用于将原始采样数据进行动态分组,使其能够组合成一定数量的样本来应用统计函数。Pandas提供了滚动、展开、指数移动等函数来建立窗口。窗口函数主要用于通过平滑曲线来以图形方式查找数据内的趋势。

滚动窗口使用.rolling()函数来建立,需要指定window参数来指定窗口中统计样本的大小。

展开窗口使用.expanding()函数来建立,需要指定min_periods参数来指定窗口中最小统计样本的大小。

.ewm()函数可以建立指数权重窗口,需要通过comspanhalflife等参数来定义权重。

聚合

聚合较为简单,主要是每列的数据进行合并操作,形成一个有代表性的统计数据的过程。聚合可以应用于DataFrame或者列,主要使用.aggregate()来完成,也可以使用其简短形式.agg()

.aggregate()可以接受一个聚合函数,或者一个聚合函数列表。.aggregate()会使用每一个聚合函数建立一列聚合数据。例如df['A'].aggregate([np.sum, np.mean])

.aggregate()还可以对多个列执行聚合操作,例如df[['A', 'B']].aggregate([np.sum, np.mean])。亦或者针对不同的列执行不同的聚合操作,例如df.aggregate({'A': np.sum, 'B': np.mean}),但是需要注意的是,.aggregate()中使用字典进行聚合的列,必须是DataFrame中存在的列。如果使用列表,则可以通过lambda表达式创建新的列,但是此时创建的列名称为<lambda>,需要使用.rename()进行改名。

分组

在许多情况下,需要对采样数据分成多个集合,并在每一个子集上应用统计函数。{\color{red} 需要注意分组与窗口的不同。}通常在执行分组后,还会继续执行的操作是聚合、变换以及过滤。

对采样数据进行分组拆分主要通过.groupby()函数来进行,.groupby()函数返回的结果是可以迭代为(key, DataFrame)结构的数据。.groupby()常用的拆分方式有以下几种。

  • .groupby(key),按照指定列标签来拆分。
  • .groupby([key1, key2]),按照指定列标签的组合来拆分。
  • .groupby(key, axis=1),按照指定行标签来拆分。

.groupby()可以接受一个as_index参数,这个参数的默认值为True。当as_indexTrue时,所有参与分组的列将变为索引。如果需要继续保留参与分组的列,并且按照原先的列名进行访问,则需要将此参数设置为False

完成分组的数据,可以通过.get_group(key)来获取一个分组的数据。而进行聚合操作,则是使用.agg()函数,而不是.aggregate()函数。

对于分组数据的转换则比较复杂,转换应该返回与组块大小相同的结果。转换使用.transform()函数完成。

.filter()函数可以接受一个函数来对已经分组的数据进行过滤,并返回符合要求的数据。

连接

Pandas具有功能全面的内存连接操作,这与关系型数据库中的连接十分相似,由于是在内存中操作,所以性能较高。对于连接操作,Pandas只提供了一个函数.merge()来实现。

.merge()的完整格式为.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True)。以下针对出现的参数及其功能进行一个简要的说明,读者可根据SQL语言中的JOIN子句的语法特性来体会.merge()函数的功能。

  • left,位于左侧的DataFrame
  • right,位于右侧的DataFrame
  • on,列的连接,指定列名必须在左右两侧的DataFrame中都存在。
  • left_on,指定左侧DataFrame中的列用于键。
  • right_on,参考left_on
  • left_index,如果为True,则使用左侧DataFrame中的行标签作为连接键。
  • right_index,参考left_index
  • sort,按照字典顺序通过连接键对结果进行排序,默认为True
  • how,确定合并时哪些键将被包含在结果表中,如果组合键没有出现在左侧或者右侧表中,则连接表中的值为NaN。可以取以下值:
    • left,左侧外连接,使用左侧对象的键。
    • right,右侧外连接,使用右侧对象的键。
    • outer,全外连接,使用键的联合。
    • inner,内连接,使用键的交集,此项为默认值。