整洁的时间序列聚合与核心PySpark

用核心PySpark移动窗口聚合策略,用Plotly实现可视化

https://media.springernature.com/lw660/springer-cms/rest/v1/img/19125576/v3/4by3?as=jpg

一个时间序列度量,其中许多度量具有相同的预处理步骤和/或用例。为了限制冗余,我将重点关注三个使用不同用例的标准:

  • 基于滚动Z-Scores的离群点检测
  • 滚动相关矩阵
  • 指数移动平均线趋势检测

第一节给出了滚动窗口和采样周期的定义。这些公式为如何开始创建这些移动窗口指标提供了有用的上下文。也可以直接跳到情节和代码;)

就像对待一切事物一样h数据,有不止一种方法烤你的数据.下面介绍一下我的背景和编程风格:我来自一个使用大量SQL的工作环境,我的聚合策略反映了这一点。因此,我没有使用PySpark表达式或内置库,也就是说,如果我可以在没有它们的情况下完成任务的话。

本文中的代码在本地PySpark环境中进行了测试,并连接到S3数据源。在这里是一篇关于如何在Windows 10上设置这个测试环境的简短教程文章。

所有的方程式、图表和图形都是我创造的。所有的绘图代码都可以找到在这里.我在所有的情节中都使用了Plotly。

移动窗口和采样周期

时间序列矩阵通常被限定在一个时间窗口内。可能有不同的粒度或采样周期,可以为度量计算,例如,10分钟、1小时、1天等。在本文的其余部分中,我将使用的描述指标的语法如公式(0)所示。

P: xm(1)矩阵
K:采样周期(10分钟、1小时等)
M:回望窗的大小
N:当前时间序列的整数索引
N:时间序列的整数索引
T:时间块内的整数索引

例如,采样周期(K)为10分钟:

t = 0时,n = 1,1 * K = 10分钟
t = 1, n = 2, 2 * K = 20分钟
t = 2, n = 3, 3 * K = 30分钟

https://gist.github.com/freedomtowin/6f1ff6cbf2a76d08d8cb90685ec9075f

块的时候,t,表示1个大小为m的时间窗口,对每个时间窗口进行聚合后,时间索引N加1。度量被聚合t,N跟踪每个窗口的全局时间索引。

基于滚动Z-Scores的离群点检测

滚动z分数阈值可用于检测时间序列中的大跳跃或间隙。这方面有许多潜在的应用程序,例如,为大的异常值创建警报系统。

z分数,或标准分数,表示离均值标准差的个数。如果您是统计学新手,您可以阅读更多关于这个指标的信息在这里.这个度量可以看作是移动平均线附近的一个置信区间。

简单移动平均和简单移动标准差将被用来创建z分数,分别如下式(1)和(2)所示。

上面的公式显示了这两个度量在时间步长N时是如何定义的,跨越大小为M-1的滚动窗口t。最后一个时间步骤M被排除在聚合时间窗口之外,因为目标是将当前时间序列值与前一个窗口的平均值和标准偏差进行比较。如果包含当前的时间步长,那么时间序列的标准差可能会大大增加,而度量将无法检测到大的变化。

执行这些滚动窗口计算后,可以计算出z分数的上下限,分别如式(3)和式(4)所示。

在这些方程中,z分数的上界和下界分别设为均值上下两个标准差。假设正态分布,经验法则我们期望99.7%的数据在标准偏差范围内。

下图显示了ATVI每小时股票价格的10HR移动平均值的z分数上限和下限。

https://gist.github.com/freedomtowin/6f1ff6cbf2a76d08d8cb90685ec9075f

绿色阴影区域表示移动平均附近的置信区间,黄色线表示时间序列,绿色线是时间序列的移动平均。在某一点上,在置信区间外有一个急剧的下降,这表明有一个大的离群值。标准偏差,随后大大增加后倾斜。有一些时间序列跨越置信区间的点,变化不是很显著。对于这个特定的时间序列,可以使用更大的z分数阈值。

注意:数据集经过预处理,包括工作日上午9点到下午4点之间的每小时数据。出于绘图的目的,这些值是根据索引而不是时间绘制的。这消除了图中的一些不连续性。

PySpark代码:

首先,创建一个排序索引来执行自连接,以便为每个时间序列(即股票符号)获得一个按时间排序的历史窗口。然后,对视图(a)中的每个值,在视图(b)中聚合移动平均和移动标准差。从这些指标,可以计算出上限和下限z分数阈值。

滚动相关矩阵

滚动相关矩阵可以帮助将相关的时间序列分组在一起,帮助发现明显的、不相关的时间序列,或检测相关模式的变化。我给您的挑战是,在不使用内置的PySpark函数的情况下创建它;)

归一化协方差皮尔逊相关系数的,描述了两个变量之间的相关性。度规在-1和1之间,这是在时间序列对之间比较这个度规时非常有用的属性。我们可以通过滚动的时间窗口计算这种相关性。

滚动相关也可以用指数移动平均函数平滑。平滑滚动相关的另一个术语是“实现的相关”。

在那里,r为我们时间序列数据集中第I列与第j列的相关关系,μ为简单移动平均,σ为简单移动标准差。

我将使用我信赖的股票数据集来绘制DoorDash每小时股价与其他股票(即ATVI、DIS、NVDA和WMT)之间的滚动相关性。

https://gist.github.com/freedomtowin/6f1ff6cbf2a76d08d8cb90685ec9075f

与其他时间序列相比,DASH和NVDA之间的相关性在较长的时间周期内似乎是一致的。同时持有这两种股票会增加投资组合的风险。

注:上图中缺失的数据点,发生在当前时间步n的任何一个时间序列的数据缺失时。例如DIS是2021年8月至2021年11月之间的数据缺失。但是,相关性窗口将跳过空值,并且在聚合中使用过去14个小时没有丢失的值。

PySpark代码:

第一步是计算数据透视表,按时间划分,按时间序列id、股票符号分组。这个数据透视表取时间序列的平均值,关闭,但是因为数据集是按小时进行预处理的,所以最小值、最大值、第一个值或最后一个值也可以作为聚合。

对于每一对时间序列,在计算滚动相关性之前,将删除两个时间序列中具有空值的行

下一步是创建时间序列的不重复对或组合。带有空值的行将从每个组合中删除。最后,我们需要计算每一对时间序列之间的相关性。幸运的是,PySpark中有一个内置函数来计算两列之间的相关性。然后,滚动关联被左连接回pivot表。

指数移动平均线趋势检测

差分指数移动平均线可以用来检测速度,或趋势,时间序列。该方法可以应用于二次检测,对不同的时间序列进行检测加速度,或趋势的变化率。

指数移动平均线(EMA)可以被看作是一个过滤器,它对聚合窗口中最近的值具有更大的重要性。均线有两个主要参数,即α衰减率和窗口大小。时间窗越大或alpha值越低,均线移动越慢。换句话说,移动平均线将比实际时间序列滞后更多。

本节中使用的趋势检测方法通常称为MACD.然而,我将用新的术语来解释这个算法,在我看来,这个术语更容易理解。

通常,alpha值等于2/(1+M),其中M是窗口大小。alpha的这个值对应于加权平均影响,或“质心”,对应于简单移动平均线(SMA)的回望窗口的中心。换句话说,对于高自相关信号(如股票价格),均线将落后于实际价格大约一半的回望窗口大小。请参阅罗伯特·诺的《预测笔记》为更多的细节。

据我所知,如果不使用用户定义的函数或UDF,在PySpark中实现递归方法(如EMAs)和谷歌搜索,是不可能的。幸运的是,在核心PySpark中有一个扩展的系列表示,可以用来计算ema。式(6)表示扩展符号的指数移动平均公式(EMA)。

通过计算快速移动(较短时间窗口)和缓慢移动(较长时间窗口)均线之间的差值,可以得出趋势可以被估计。直观上,这可以被认为是最近价格和以前价格之间的斜率或离散导数。这些EMAs之间的区别可以称为速度的趋势。

这种趋势变化的速度也可以用1)速度2)平均线速度(或信号)。

两者之间的区别信号速度可以认为是加速度的趋势速度和信号之间的收敛代表趋势方向的逆转。这种差异代表着一种日益强劲的趋势。

https://gist.github.com/freedomtowin/6f1ff6cbf2a76d08d8cb90685ec9075f

上面的图表显示了时间序列(黄色),缓慢的EMA(蓝色)和快速的EMA(红色)。底部的图表显示加速度(柱状图),这一趋势速度(红色)和信号(蓝色)。该图显示了在短时间间隔内趋势上的一些一致性。当然,可能会有一些安全阈值的加速度这可以用来探测强劲的上升和下降。

注意:因为我选择K=3作为采样周期,所以这个图看起来有点不稳定。

PySpark代码:

创建了一个单独的函数来计算大小为m的特定窗口的EMA。在这个函数中,创建了一个排序索引来执行一个自连接,以便为每个分区(即股票符号)获得一个按时间排序的历史窗口。历史窗口索引和当前索引之间的差值被用来为EMA公式的扩展序列表示创建alpha权值,如公式8所示。最后,对于视图(a)中的每个值,EMA在视图(b)中被聚合。

我们可以使用EMA函数来计算快速移动的EMA,缓慢移动的EMA,快速和缓慢EMA之间的差值(速度),以及速度的EMA(信号)。

结论

简单地说,本文展示了如何在PySpark和SQL中聚合时间序列。我知道时间序列窗口和方程的正式定义使这篇文章更难阅读。不过,我喜欢做得彻底。)我也可能把这篇文章分成三篇。尽管如此,仍然希望PySpark和Plotly代码对一些新的数据科学家和工程师有用。

以下是一些你可以尝试的数据挑战:

  1. 在离群点检测算法中,使用指数移动平均代替简单移动平均。
  2. 编写自己的相关函数,而不是使用内置的PySpark相关函数。探索实现类似的度量标准,例如:协整
  3. 使用指数移动平均线创建平滑移动窗口相关矩阵。
  4. 表征跨M1、M2和M3多个参数的趋势检测方法的有效性。

这是所有的人。

Baidu
map