Apache Spark聚合:基于另一个列值聚合列

时间:2019-12-10 13:16:33

标签: scala apache-spark aggregate

我不确定我是否正确提出了这个问题,也许这就是到目前为止我找不到正确答案的原因。无论如何,如果将重复,我将删除此问题。

我有以下数据:

id | last_updated | count
__________________________
1  | 20190101     | 3
1  | 20190201     | 2
1  | 20190301     | 1 

我想按“ id”列对数据进行分组,从“ last_updated”获取最大值,关于“ count”列,我希望保留“ last_updated”具有最大值的行的值。因此,在这种情况下,结果应该是这样的:

id | last_updated | count
__________________________
1  | 20190301     | 1 

所以我想它看起来像这样:

df
  .groupBy("id")
  .agg(max("last_updated"), ... ("count"))

我是否可以使用任何函数基于“ last_updated”列获取“计数”。

我正在使用spark 2.4.0。

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

您有两种选择,根据我的理解,第一种更好。

选项1 在ID上执行窗口函数,创建一个具有该窗口函数最大值的列。然后选择所需列等于最大值的位置,最后删除该列并根据需要重命名max列

val w  = Window.partitionBy("id")

df.withColumn("max", max("last_updated").over(w))
  .where("max = last_updated")
  .drop("last_updated")
  .withColumnRenamed("max", "last_updated")

选项2

您可以在分组后与原始数据框执行联接

df.groupBy("id")
.agg(max("last_updated").as("last_updated"))
.join(df, Seq("id", "last_updated"))

快速示例

输入

df.show
+---+------------+-----+
| id|last_updated|count|
+---+------------+-----+
|  1|    20190101|    3|
|  1|    20190201|    2|
|  1|    20190301|    1|
+---+------------+-----+

输出 选项1

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

val w  = Window.partitionBy("id") 

df.withColumn("max", max("last_updated").over(w))
  .where("max = last_updated")
  .drop("last_updated")
  .withColumnRenamed("max", "last_updated")


+---+-----+------------+
| id|count|last_updated|
+---+-----+------------+
|  1|    1|    20190301|
+---+-----+------------+

选项2

  df.groupBy("id")
      .agg(max("last_updated").as("last_updated")
      .join(df, Seq("id", "last_updated")).show


    +---+-----------------+----------+
    | id|     last_updated|    count |
    +---+-----------------+----------+
    |  1|         20190301|         1|
    +---+-----------------+----------+