首頁 > 資料庫 > mysql教程 > 如何在Spark中有效率地選擇每個組的頂行?

如何在Spark中有效率地選擇每個組的頂行?

Susan Sarandon
發布: 2025-01-23 12:57:10
原創
968 人瀏覽過

How to Efficiently Select the Top Row for Each Group in Spark?

高效率選擇每個分組的首行

本文旨在擷取每個「小時」和「類別」分組中「總值」最高的那一行資料。 有多種方法可以實現:

使用視窗函數:

視窗函數提供了一種在每個分組內進行計算的有效方法。 以下是一種實作方式:

<code>import org.apache.spark.sql.functions.{row_number, max, broadcast}
import org.apache.spark.sql.expressions.Window

val w = Window.partitionBy($"Hour").orderBy($"TotalValue".desc)

val dfTop = df.withColumn("rn", row_number.over(w)).where($"rn" === 1).drop("rn")</code>
登入後複製

使用SQL聚合和連接:

另一種方法是利用SQL聚合和後續連接:

<code>val dfMax = df.groupBy($"Hour".as("max_hour")).agg(max($"TotalValue").as("max_value"))

val dfTopByJoin = df.join(broadcast(dfMax),
    ($"Hour" === $"max_hour") && ($"TotalValue" === $"max_value"))
  .drop("max_hour")
  .drop("max_value")</code>
登入後複製

使用結構體排序:

一個巧妙的方法是對包含「總值」和「類別」的結構體進行排序:

<code>val dfTop = df.select($"Hour", struct($"TotalValue", $"Category").alias("vs"))
  .groupBy($"Hour")
  .agg(max("vs").alias("vs"))
  .select($"Hour", $"vs.Category", $"vs.TotalValue")</code>
登入後複製

使用DataSet API (Spark 1.6 ):

DataSet API提供了一種簡潔的方法來實現相同的結果:

<code>case class Record(Hour: Integer, Category: String, TotalValue: Double)

df.as[Record]
  .groupBy($"Hour")
  .reduce((x, y) => if (x.TotalValue > y.TotalValue) x else y)</code>
登入後複製

避免錯誤方法:

以下方法可能會產生不可靠的結果,應避免使用:

  • df.orderBy(...).groupBy(...).agg(first(...), ...)
  • df.orderBy(...).dropDuplicates(...)

以上是如何在Spark中有效率地選擇每個組的頂行?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板