如何将当前行的值除以以下值?

时间:2017-06-06 14:27:31

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

在Spark-Sql 1.6版中,使用DataFrame s,是否有办法为特定列计算每行的当前行和下一行的分数?

例如,如果我有一个包含一列的表,就像这样

Age
100
50
20
4

我想要以下输出

Franction
2
2.5
5

最后一行被删除,因为它没有要添加的“下一行”。

现在我正在通过对表格进行排名并将其与自身结合来实现,其中rank等于rank+1

有更好的方法吗? 可以使用Window函数来完成吗?

1 个答案:

答案 0 :(得分:3)

Window函数应该只做部分技巧。其他部分技巧可以通过定义udf函数

来完成
def div = udf((age: Double, lag: Double) => lag/age)

首先,我们需要使用lag函数找到Window,然后在lag函数中传递ageudf来查找div }     import sqlContext.implicits._     import org.apache.spark.sql.functions ._

val dataframe = Seq(
  ("A",100),
  ("A",50),
  ("A",20),
  ("A",4)
).toDF("person", "Age")

val windowSpec = Window.partitionBy("person").orderBy(col("Age").desc)
val newDF = dataframe.withColumn("lag", lag(dataframe("Age"), 1) over(windowSpec))

最后调用udf函数

newDF.filter(newDF("lag").isNotNull).withColumn("div", div(newDF("Age"), newDF("lag"))).drop("Age", "lag").show

最终输出将是

+------+---+
|person|div|
+------+---+
|     A|2.0|
|     A|2.5|
|     A|5.0|
+------+---+

<强>被修改 由于@Jacek建议使用.na.drop代替.filter(newDF("lag").isNotNull)并使用/运算符的更好解决方案,因此我们甚至不需要调用udf函数< / p>

newDF.na.drop.withColumn("div", newDF("lag")/newDF("Age")).drop("Age", "lag").show