Spark'加入'带有List和返回String的DataFrame

时间:2018-02-15 00:00:27

标签: scala apache-spark join apache-spark-sql

我有以下DataFrame:

DF1:
+------+---------+
|key1  |Value    |
+------+---------+
|[k, l]|      1  |
|[m, n]|      2  |
|[o]   |      3  |
+------+---------+

需要加入'与另一个数据帧

DF2:
+----+
|key2|
+----+
|k   |
|l   |
|m   |
|n   |
|o   |
+----+

以便输出如下所示:

DF3:
+--------------------+---------+
|key3                |Value    |
+--------------------+---------+
|k:1 l:1 m:0 n:0 o:0 |      1  |
|k:0 l:0 m:1 n:1 o:0 |      2  |
|k:0 l:0 m:0 n:0 o:1 |      3  |
+--------------------+---------+

换句话说,输出数据框应该有一个列,该列是DF2中所有行的字符串,每个元素后面应该跟一个1或0,表示该元素是否存在于DF1列key1的列表中。

我不知道该怎么做。是否有一个简单的UDF我可以编写来完成我想要的东西?

1 个答案:

答案 0 :(得分:2)

这样的操作可以DF2,所以你可以使用udf

import spark.implicits._
import org.apache.spark.sql.functions._

val df1 = Seq(
  (Seq("k", "l"), 1), (Seq("m", "n"), 2), (Seq("o"), 3)
).toDF("key1", "value")
val df2 = Seq("k", "l", "m", "n", "o").toDF("key2")

val keys = df2.as[String].collect.map((_, 0)).toMap

val toKeyMap = udf((xs: Seq[String]) => 
   xs.foldLeft(keys)((acc, x) => acc + (x -> 1)))


df1.select(toKeyMap($"key1").alias("key3"), $"value").show(false)

// +-------------------------------------------+-----+
// |key3                                       |value|
// +-------------------------------------------+-----+
// |Map(n -> 0, m -> 0, l -> 1, k -> 1, o -> 0)|1    |
// |Map(n -> 1, m -> 1, l -> 0, k -> 0, o -> 0)|2    |
// |Map(n -> 0, m -> 0, l -> 0, k -> 0, o -> 1)|3    |
// +-------------------------------------------+-----+

如果你只想要一个字符串:

val toKeyMapString = udf((xs: Seq[String]) => 
   xs.foldLeft(keys)((acc, x) => acc + (x -> 1))
     .map { case (k, v) => s"$k: $v" }
     .mkString(" ")
)


df1.select(toKeyMapString($"key1").alias("key3"), $"value").show(false)
// +------------------------+-----+
// |key3                    |value|
// +------------------------+-----+
// |n: 0 m: 0 l: 1 k: 1 o: 0|1    |
// |n: 1 m: 1 l: 0 k: 0 o: 0|2    |
// |n: 0 m: 0 l: 0 k: 0 o: 1|3    |
// +------------------------+-----+