比较Spark中当前行和上一行的值

时间:2017-09-13 12:26:17

标签: scala apache-spark apache-spark-sql

我正在尝试比较下面DataFrame中当前行和上一行的记录。我想计算金额列。

scala> val dataset = sc.parallelize(Seq((1, 123, 50), (2, 456, 30), (3, 456, 70), (4, 789, 80))).toDF("SL_NO","ID","AMOUNT")

scala> dataset.show
+-----+---+------+
|SL_NO| ID|AMOUNT|
+-----+---+------+
|    1|123|    50|
|    2|456|    30|
|    3|456|    70|
|    4|789|    80|
+-----+---+------+

计算逻辑:

  1. 对于第1行,AMOUNT应该是第一行的50。
  2. 对于第2行,如果SL_NO - 2和1的ID不相同则需要考虑 SL_NO - 2的数量(即 - 30)。否则AMOUNT为SL_NO - 1(即 - 50)
  3. 对于第3行,如果SL_NO - 3和2的ID不相同则需要考虑 SL_NO - 3的数量(即 - 70)。否则AMOUNT的SL_NO - 2(即 - 30)
  4. 其他行也需要遵循相同的逻辑。

    预期输出:

    +-----+---+------+
    |SL_NO| ID|AMOUNT|
    +-----+---+------+
    |    1|123|    50|
    |    2|456|    30|
    |    3|456|    30|
    |    4|789|    80|
    +-----+---+------+
    

    请帮忙。

1 个答案:

答案 0 :(得分:5)

您可以将lagwhen.otherwise一起使用,这是一个演示:

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

val w = Window.orderBy($"SL_NO")
dataset.withColumn("AMOUNT", 
    when($"ID" === lag($"ID", 1).over(w), lag($"AMOUNT", 1).over(w)).otherwise($"AMOUNT")
).show

+-----+---+------+
|SL_NO| ID|AMOUNT|
+-----+---+------+
|    1|123|    50|
|    2|456|    30|
|    3|456|    30|
|    4|789|    80|
+-----+---+------+

注意:由于此示例不使用任何分区,因此可能存在性能问题,在您的实际数据中,如果您的问题可以通过某些变量进行分区会有所帮助,可能是{ {1}}取决于您的实际问题以及ID是否一起排序。