pandas中的窗口处理函数

2020-07-14 16:02:29 浏览数 (1)

滑动窗口的处理方式在实际的数据分析中比较常用,在生物信息中,很多的算法也是通过滑动窗口来实现的,比如经典的质控软件Trimmomatic, 从序列5'端的第一个碱基开始,计算每个滑动窗口内的碱基质量平均值,当滑动窗后的平均碱基质量值小于给定阈值时,去除该窗口以及之后的剩余碱基,以此达到去除低质量碱基的目的。

在pandas中,提供了一系列按照窗口来处理序列的函数。首先是窗口大小固定的处理方式,对应以rolling开头的函数,基本用法如下

代码语言:javascript复制
>>> s = pd.Series([1, 2, 3, np.nan, 4])
>>> s.rolling(window=2).count()
0 1.0
1 2.0
2 2.0
3 1.0
4 1.0
dtype: float64

window参数指定窗口的大小,在rolling系列函数中,窗口的计算规则并不是常规的向后延伸,而是采用了向前延伸的方式。以上述代码为例,count函数用于计算每个窗口内非NaN值的个数,对于第一个元素1,再往前就是下标-1了,序列中不存在这个元素,所以该窗口内的有效数值就是1。对于第二个元素2,往前延伸1,此时窗口内的元素为1和2,有效数值为2。接下来依次类推,就可以得到完整的输出结果了。

对于一个窗口内的全部元素,除了计数外,还提供了以下多种功能

代码语言:javascript复制
# 求和
>>> s.rolling(window=2).sum()
0 NaN
1 3.0
2 5.0
3 NaN
4 NaN
dtype: float64
# 均值
>>> s.rolling(window=2).mean()
0 NaN
1 1.5
2 2.5
3 NaN
4 NaN
dtype: float64
# 中位数
>>> s.rolling(window=2).median()
0 NaN
1 1.5
2 2.5
3 NaN
4 NaN
dtype: float64
# 方差
>>> s.rolling(window=2).var()
0 NaN
1 0.5
2 0.5
3 NaN
4 NaN
dtype: float64
# 标准差
>>> s.rolling(window=2).std()
0 NaN
1 0.707107
2 0.707107
3 NaN
4 NaN
dtype: float64
# 百分位数
>>> s.rolling(window=2).quantile(.4)
0 NaN
1 1.4
2 2.4
3 NaN
4 NaN
dtype: float64
# 最小值
>>> s.rolling(window=2).min()
0 NaN
1 1.0
2 2.0
3 NaN
4 NaN
dtype: float64
# 最大值
>>> s.rolling(window=2).max()
0 NaN
1 2.0
2 3.0
3 NaN
4 NaN
dtype: float64

除了单一功能的内置函数外,还提供了以下两种方式,agg可以聚合多个函数的结果,apply则提高了灵活性,允许自定义函数,用法如下

代码语言:javascript复制
>>> s.rolling(window=2).agg({'A':'sum', 'B':'count'})
     A B
0  NaN  1.0
1  3.0  2.0
2  5.0  2.0
3  NaN  1.0
4  NaN  1.0

>>> s.rolling(window=2).apply(lambda x:np.nanmean(x))
0    NaN
1    1.5
2    2.5
3    NaN
4    NaN
dtype: float64

与固定窗口相对应,pandas还提供了一种窗口大小可变的处理方式,对应expanding函数,基本用法如下

代码语言:javascript复制
>>> s
0 1.0
1 2.0
2 3.0
3 NaN
4 4.0
dtype: float64

>>> s.expanding(min_periods=2).count()
0 NaN
1 2.0
2 3.0
3 3.0
4 4.0
dtype: float64

min_periods参数指定窗口内最小的有效数值个数,只有当满足这个条件时,才进行后续运算,否则返回NaN。以上述代码为例,expanding的窗口也是向前延伸,不同之处在于它会延伸到起始的第一个元素。对于第一个元素而言,其窗口只有1个元素,不符合最小有效数值的要求,所以返回NaN。对于第二个元素而言,窗口内包含1和2两个元素;对于第三个元素而言,窗口内包含了1,2,3共3个元素,依次类推,就可以得到上述结果。

从上述逻辑可以发现,expanding实现了一种累积的计算方式。对于expanding系列函数而言,rolling对应的函数expanding也都有,部分函数示例如下

代码语言:javascript复制
>>> s.expanding(min_periods=2).mean()
0 NaN
1 1.5
2 2.0
3 2.0
4 2.5
dtype: float64
>>> s.expanding(min_periods=2).median()
0 NaN
1 1.5
2 2.0
3 2.0
4 2.5
dtype: float64
>>> s.expanding(min_periods=2).std()
0 NaN
1 0.707107
2 1.000000
3 1.000000
4 1.290994
dtype: float64
>>> s.expanding(min_periods=2).var()
0 NaN
1 0.500000
2 1.000000
3 1.000000
4 1.666667
dtype: float64

通过rolling和expanding系列函数,可以按照窗口的方式来灵活处理序列。

·end·

0 人点赞