有关Spark数据帧操作的问题

时间:2018-01-29 06:18:44

标签: scala apache-spark dataframe

如果我创建这样的数据框:

val df1 = sc.parallelize(List((1, 1), (1, 1), (1, 1), (1, 2), (1, 2), (1, 3), (2, 1), (2, 2), (2, 2), (2, 3)).toDF("key1","key2")

然后我按" key1"和" key2"和count" key2"。

val df2 = df1.groupBy("key1","key2").agg(count("key2") as "k").sort(col("k").desc)

我的问题是如何过滤这个数据帧并留下" k"的前2个数字。来自每个" key1"?

如果我不使用窗口功能,我该怎样解决这个问题?

1 个答案:

答案 0 :(得分:1)

这可以使用窗口函数来完成,使用row_number()(或rank() / dense_rank(),具体取决于您的要求):

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

df2
  .withColumn("rnb", row_number().over(Window.partitionBy($"key1").orderBy($"k".desc)))
  .where($"rnb" <= 2).drop($"rnb")
  .show()

编辑:

这是一个使用RDD的解决方案(不需要HiveContext):

df2
  .rdd
  .groupBy(_.getAs[Int]("key1"))
  .flatMap{case (_,rows) => {
    rows.toSeq
      .sortBy(_.getAs[Long]("k")).reverse
      .take(2)
      .map{case Row(key1:Int,key2:Int,k:Long) => (key1,key2,k)}
   }
 }
.toDF("key1","key2","k")
.show()