Spark DataFrame组中的最后一个对象

时间:2019-02-01 08:53:34

标签: scala apache-spark

我需要为给定的“ id”选择最后一个“ name”。可能的解决方案如下:

val channels = sessions
    .select($"start_time", $"id", $"name")
    .orderBy($"start_time")
    .select($"id", $"name")
    .groupBy($"id")
    .agg(last("name"))

我不知道它是否正确,因为我不确定执行orderBy后是否保留groupBy

但这当然不是一个高效的解决方案。可能我应该使用reduceByKey。我在spark壳中尝试了以下方法,并且有效

val x = sc.parallelize(Array(("1", "T1"), ("2", "T2"), ("1", "T11"), ("1", "T111"), ("2", "T22"), ("1", "T100"), ("2", "T222"), ("2", "T200")), 3)
x.reduceByKey((acc,x) => x).collect

但是它不适用于我的数据框。

case class ChannelRecord(id: Long, name: String)
val channels = sessions
    .select($"start_time", $"id", $"name")
    .orderBy($"start_time")
    .select($"id", $"name")
    .as[ChannelRecord]
    .reduceByKey((acc, x) => x) // take the last object

我遇到了一个编译错误:值reduceByKey不是org.apache.spark.sql.Dataset的成员

我认为我应该在进行map()之前添加一个reduceByKey通话,但是我不知道应该映射什么。

1 个答案:

答案 0 :(得分:3)

例如,您可以使用窗口功能来实现。这将需要在id列上进行洗牌,并在start_time上进行排序。

有两个阶段:

  • 获取每个ID的姓氏
  • 仅保留姓氏(最大开始时间)的行

示例数据框:

val rowsRdd: RDD[Row] = spark.sparkContext.parallelize(
Seq(
Row(1, "a",  1),
Row(1, "b",  2),
Row(1, "c",  3),
Row(2, "d",  4),
Row(2, "e",  5),
Row(2, "f",  6),
Row(3, "g",  7),
Row(3, "h",  8)
))


val schema: StructType = new StructType()
.add(StructField("id",             IntegerType,  false))
.add(StructField("name",           StringType,  false))
.add(StructField("start_time",     IntegerType, false))


val df0: DataFrame = spark.createDataFrame(rowsRdd, schema)

定义一个窗口。请注意,我在这里按start_time降序排列。这样便可以在下一步中选择第一行。

val w = Window.partitionBy("id").orderBy(col("start_time").desc)

然后

df0.withColumn("last_name", first("name").over(w)) // get first name for each id (first because of decreasing start_time)
.withColumn("row_number", row_number().over(w)) // get row number for each id sorted by start_time
.filter("row_number=1") // choose only first rows (first row = max start_time)
.drop("row_number") // get rid of row_number columns
.sort("id")
.show(10, false)

这将返回

+---+----+----------+---------+
|id |name|start_time|last_name|
+---+----+----------+---------+
|1  |c   |3         |c        |
|2  |f   |6         |f        |
|3  |h   |8         |h        |
+---+----+----------+---------+