如果我创建这样的数据框:
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"?
如果我不使用窗口功能,我该怎样解决这个问题?
答案 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()