我有一个以下结构的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值
答案 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|
+-------+----+-----+---------+