使用Spark对分组数据进行快速行间计算

时间:2017-06-06 17:32:03

标签: python apache-spark

我有一个以下结构的CSV文件(> 3GB)

groupId | time | value
1            0       2 
1            1       1 
1            2       4 
2            0       6 
2            1       2 

并且想要添加一个列(值t-1),其中包含值 - 在同一组中 - 前一个时间步的“行”:

groupId | time | value | value t-1
1            0       2           -
1            1       1           2
1            2       4           1
2            0       6           -
2            1       2           6

我认为昂贵的部分是搜索前一行。不知怎的,如果这有意义的话,它似乎可以减少地图的工作量而不会减少。但据我了解,我不能确定同一个工作组中的同一组的所有数据。

Spark是否适合这项工作?

我最好的替代解决方案是将文件拆分为多个文件(每组一个),然后运行多个python脚本实例,对其进行排序并依次添加值t-1值

1 个答案:

答案 0 :(得分:2)

这可以通过使用spark的Window功能来实现,如下所示。

import org.apache.spark.sql.expressions.Window

val df = Seq((1,0,2), (1,1,1), (1,2,4), (2,0,6), (2,1,2)).toDF("groupId", "time", "value")

val result = df.withColumn("value_t-1", sum($"value").over(Window.partitionBy("groupId").orderBy("time").rowsBetween(-1,-1)))

<强>输出:

scala> result.show()
+-------+----+-----+---------+
|groupId|time|value|value_t-1|
+-------+----+-----+---------+
|      1|   0|    2|     null|
|      1|   1|    1|        2|
|      1|   2|    4|        1|
|      2|   0|    6|     null|
|      2|   1|    2|        6|
+-------+----+-----+---------+

Python版

>>> from pyspark.sql.window import Window
>>> import pyspark.sql.functions as func
>>> df = spark.createDataFrame([(1,0,2), (1,1,1), (1,2,4), (2,0,6), (2,1,2)], ["groupId", "time", "value"])
>>> result = df.withColumn("value_t-1", func.sum(df.value).over(Window.partitionBy(df.groupId).orderBy(df.time).rowsBetween(-1,-1)))
>>> result.show()
+-------+----+-----+---------+
|groupId|time|value|value_t-1|
+-------+----+-----+---------+
|      1|   0|    2|     null|
|      1|   1|    1|        2|
|      1|   2|    4|        1|
|      2|   0|    6|     null|
|      2|   1|    2|        6|
+-------+----+-----+---------+