【问题标题】:How to divide the value of current row with the following one?如何将当前行的值与以下行相除?
【发布时间】:2017-11-07 15:10:53
【问题描述】:

在 Spark-Sql 版本 1.6 中,使用DataFrames,有没有一种方法可以为特定列计算每一行当前行与下一行相除的分数?

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

Age
100
50
20
4

我想要以下输出

Franction
2
2.5
5

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

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

有没有更好的方法来做到这一点? 这可以通过Window 函数完成吗?

【问题讨论】:

  • 是的。这就是窗口聚合函数的“工作”。你用/了吗?
  • @JacekLaskowski,我在functions 中找不到/ 或类似内容。

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


【解决方案1】:

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

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

首先我们需要使用Window 函数找到lag,然后将lagage 传递给udf 函数以找到div 导入 sqlContext.implicits._ 导入 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 函数

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

【讨论】:

  • 谢谢。根据您的回答,我编写了以下内容(无 UDF):dataframe.select($"person", $"Age"/ (lead("Age", 1) over windowSpec) as "div").na.drop.show
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 2016-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
相关资源
最近更新 更多