Spark SQL –如何根据动态生成的密钥进行分组或聚合?

时间:2019-08-04 03:57:35

标签: apache-spark apache-spark-sql

我有一个重叠的有序数组的DataFrame。

[1,2,3]    
[2,3,4]    
[7,8,9]

使用Spark SQL,我想将重叠的部分归为一组,如下所示:

Key  Values 
1    [1,2,3], [2,3,4] 
2    [7,8,9]

我一直在研究UDAF函数,但是不明白如何为符合合并条件的行生成新的键。

目前,我是在驱动程序端实现的,如下所示:

  1. 按数组的第一个和最后一个元素排序数组的集合。
  2. 在循环中,如果数组中的第一个元素小于或等于前一个数组的最后一个元素,则将它们放在同一存储桶中。

这可行,但是要做到这一点,我需要在驱动程序端收集所有数据,我正在寻找一种更有效的方法。

1 个答案:

答案 0 :(得分:1)

这是我可以帮助解决这种情况的方法。 说明:

  1. 首先找到长度大于1的数组的排列
  2. 分解排列数组
  3. 按排列数组分组并收集原始数组列表
  4. 获取原始数组列表的区别
import org.apache.spark.sql.functions._
val y = sc.parallelize(Seq(Seq(1,2,3),Seq(2,3,4),Seq(7,8,9))).toDF("arr")
val x = (s:Seq[Int]) => s.toSet[Int].subsets.filter(_.size>1).map(_.toList).toList
val permutations = udf(x)
val a = y.select($"arr", permutations($"arr").as("permutations"))
a.select($"arr", explode($"permutations").as("permutations")).groupBy("permutations").agg(collect_set($"arr").as("groups")).select($"groups").distinct().select(monotonicallyIncreasingId, $"groups").show(false)

//+-----------------------------+----------------------+
//|monotonically_increasing_id()|groups                |
//+-----------------------------+----------------------+
//|214748364800                 |[[1, 2, 3], [2, 3, 4]]|
//|412316860416                 |[[7, 8, 9]]           |
//|884763262976                 |[[1, 2, 3]]           |
//|1056561954816                |[[2, 3, 4]]           |
//+-----------------------------+----------------------+

我希望这会帮助您入门。有很多小问题,我会留给你的。