有没有办法用Spark的数据帧和Window.partitionBy做(连续)移动平均线?

时间:2017-11-17 17:29:10

标签: python apache-spark pyspark pyspark-sql

我正在处理大型时间序列数据集,并希望能够计算其中某些读数的移动平均值。数量级大约为50 Hz,每个文件有几天的数据。

我知道我可以使用一个窗口对其周围几秒钟的读数进行读数的移动平均值:

window_avg = Window.orderBy("time").rowsBetween(-100,100) # Just using 100 for example
res = df.withColumn("avg", avg("reading").over(window_avg)).sort("time")

但是,我在没有定义分区的情况下读到了这个,它将在一个执行器上运行。为了避免这种情况,我可以像这样定义一个分区:

window_avg = Window.partitionBy("hour").orderBy("time").rowsBetween(-100,100)
res = df.withColumn("avg", avg("reading").over(window_avg)).sort("time")

但在这种情况下,每个分区的前几行不会引用前一个分区的前一行。

是否有一种方法可以定义重叠的窗口分区,或者像rowsBetween这样的东西引用以前的分区?我相信我看过有关使用RDD执行类似操作的帖子,但没有使用Window分区。

作为参考,这是一组简化的数据示例:

minute,time,reading
1,1.57,1
1,1.58,2
1,1.59,3
2,2.0,2
2,2.1,3
2,2.2,2
2,2.3,5
2,2.4,9
2,2.5,2

我可以像这样读取滚动平均值:

df = spark.read.csv('foo.csv', header=True)

window_avg = Window.partitionBy("minute").orderBy("time").rowsBetween(-1,1)
res = df.withColumn("avg", avg("reading").over(window_avg)).sort("time")
print res.collect()

我想要以下输出:

 [Row(minute=u'1', time=u'1.57', reading=u'1', avg=1.5), 
  Row(minute=u'1', time=u'1.58', reading=u'2', avg=2.0), 
  Row(minute=u'1', time=u'1.59', reading=u'3', avg=2.3333333333333335), 
  Row(minute=u'2', time=u'2.0', reading=u'2', avg=2.6666666666666665), 
  Row(minute=u'2', time=u'2.1', reading=u'3', avg=2.3333333333333335), 
  Row(minute=u'2', time=u'2.2', reading=u'2', avg=3.3333333333333335), 
  Row(minute=u'2', time=u'2.3', reading=u'5', avg=5.333333333333333), 
  Row(minute=u'2', time=u'2.4', reading=u'9', avg=5.333333333333333), 
  Row(minute=u'2', time=u'2.5', reading=u'2', avg=5.5)]

但是{分钟'partitionBy,我得到了:

[Row(minute=u'1', time=u'1.57', reading=u'1', avg=1.5), 
 Row(minute=u'1', time=u'1.58', reading=u'2', avg=2.0), 
 Row(minute=u'1', time=u'1.59', reading=u'3', avg=2.5), 
 Row(minute=u'2', time=u'2.0', reading=u'2', avg=2.5), 
 Row(minute=u'2', time=u'2.1', reading=u'3', avg=2.3333333333333335), 
 Row(minute=u'2', time=u'2.2', reading=u'2', avg=3.3333333333333335), 
 Row(minute=u'2', time=u'2.3', reading=u'5', avg=5.333333333333333), 
 Row(minute=u'2', time=u'2.4', reading=u'9', avg=5.333333333333333), 
 Row(minute=u'2', time=u'2.5', reading=u'2', avg=5.5)]

对于分区,在边界处,时间1.59处的平均值具有不正确的平均值,而对于2.0具有不正确的平均值。

0 个答案:

没有答案