sparkDataframe来自数组列的所有组合

mnemlml8  于 2021-05-17  发布在  Spark
关注(0)|答案(1)|浏览(378)

假设我有一个sparkDataframe d1 有两列, elements_1 以及 elements_2 ,包含大小为的整数集 k ,和 value_1 , value_2 包含整数值的。例如,使用 k = 3 :

d1 = 
+------------+------------+
| elements_1 | elements_2 |
+-------------------------+
| (1, 4, 3)  |  (3, 4, 5) |
| (2, 1, 3)  |  (1, 0, 2) |
| (4, 3, 1)  |  (3, 5, 6) |
+-------------------------+

我需要创建一个新列 combinations 每对套装包含 elements_1 以及 elements_2 ,所有可能的元素组合的集合列表。这些集合必须具有以下属性:
它们的大小必须是 k+1 它们必须包含 elements_1 或是在 elements_2 例如,从 (1, 2, 3) 以及 (3, 4, 5) 我们获得 [(1, 2, 3, 4), (1, 2, 3, 5), (3, 4, 5, 1) and (3, 4, 5, 2)] . 列表不包含 (1, 2, 5) 因为它不长 3+1 ,并且它不包含 (1, 2, 4, 5) 因为它既不包含原始集合。

d8tt03nd

d8tt03nd1#

您需要创建一个自定义的用户定义函数来执行转换,从中创建一个spark兼容的userdefinedfunction,然后使用withcolumn应用。实际上,这里有两个问题:(1)如何进行所描述的集合转换,(2)如何使用用户定义的函数在Dataframe中创建一个新列。
这是设置逻辑的第一次尝试,请告诉我它是否符合您的要求:

def combo[A](a: Set[A], b: Set[A]): Set[Set[A]] = 
    a.diff(b).map(b+_) ++ b.diff(a).map(a+_)

现在创建udf Package 器。请注意,在引擎盖下,这些集合都由wrappedarray表示,因此我们需要处理这个问题。通过定义一些隐式转换,可能有一种更优雅的方法来处理这个问题,但这应该是可行的:

import scala.collection.mutable.WrappedArray
val comboWrap: (WrappedArray[Int],WrappedArray[Int])=>Array[Array[Int]] = 
    (x,y) => combo(x.toSet,y.toSet).map(_.toArray).toArray
val comboUDF = udf(comboWrap)

最后,通过创建新列将其应用于Dataframe:

val data = Seq((Set(1,2,3),Set(3,4,5))).toDF("elements_1","elements_2")
val result = data.withColumn("result", 
    comboUDF(col("elements_1"),col("elements_2")))
result.show

相关问题