Spark Dataframe groupBy并将结果排序到列表中

时间:2016-08-01 05:04:12

标签: apache-spark dataframe apache-spark-sql

我有一个Spark Dataframe,我想按键对元素进行分组,并将结果作为排序列表

目前我正在使用:

df.groupBy("columnA").agg(collect_list("columnB"))

如何使列表中的项目按升序排序?

2 个答案:

答案 0 :(得分:20)

您可以尝试functions包中提供的功能sort_array

import org.apache.spark.sql.functions._
df.groupBy("columnA").agg(sort_array(collect_list("columnB")))

答案 1 :(得分:5)

只是想在Daniel de Paula的答案中添加关于sort_array解决方案的另一个提示。

如果要根据不同的列对元素进行排序,则可以形成两个字段的结构:

  • 排序依据字段
  • 结果字段

由于结构是按字段进行排序的,因此您将获得所需的顺序,您所需要的就是摆脱结果列表每个元素中的排序依据列。
必要时,可以对多个 sort by 列应用相同的方法。

这是一个示例,可以在本地spark-shell(使用:paste模式下)中运行

import org.apache.spark.sql.Row
import spark.implicits._

case class Employee(name: String, department: String, salary: Double)

val employees = Seq(
  Employee("JSMITH", "A", 20.0),
  Employee("AJOHNSON", "A", 650.0),
  Employee("CBAKER", "A", 650.2),
  Employee("TGREEN", "A", 13.0),
  Employee("CHORTON", "B", 111.0),
  Employee("AIVANOV", "B", 233.0),
  Employee("VSMIRNOV", "B", 11.0)
)

val employeesDF = spark.createDataFrame(employees)

val getNames = udf { salaryNames: Seq[Row] =>
  salaryNames.map { case Row(_: Double, name: String) => name }
}

employeesDF
  .groupBy($"department")
  .agg(collect_list(struct($"salary", $"name")).as("salaryNames"))
  .withColumn("namesSortedBySalary", getNames(sort_array($"salaryNames", asc = false)))
  .show(truncate = false)

结果:

+----------+--------------------------------------------------------------------+----------------------------------+
|department|salaryNames                                                         |namesSortedBySalary               |
+----------+--------------------------------------------------------------------+----------------------------------+
|B         |[[111.0, CHORTON], [233.0, AIVANOV], [11.0, VSMIRNOV]]              |[AIVANOV, CHORTON, VSMIRNOV]      |
|A         |[[20.0, JSMITH], [650.0, AJOHNSON], [650.2, CBAKER], [13.0, TGREEN]]|[CBAKER, AJOHNSON, JSMITH, TGREEN]|
+----------+--------------------------------------------------------------------+----------------------------------+