我试图弄清楚如何连接两个数据帧,其中一个数据帧包含一个列表,该列表具有要加入的键。
例如:
(id: String, ...,...)
(... ,..., List[tmpObj])
tmpObj
的结构如下(id: String, value: int)
。我的目标是通过第二个dataFrame的tmpObj列表中的id值将这两个数据帧连接到第一个数据帧的id。
有没有人知道如何解决这个问题?
答案 0 :(得分:1)
你可以编写一个UDF来检查列表是否包含给定的id:
val df1 = Seq("a","b","c").toDF("id")
case class TmpObject(id:String,value:Int)
val df2 = Seq(
Seq(
TmpObject("a",1),
TmpObject("c",2)
)
).toDF("list")
val arrayContains = udf((xs:Seq[String],s:String) => xs.contains(s))
df1.join(df2,arrayContains($"list.id",$"id"),"left")
.show()
+---+--------------+
| id| list|
+---+--------------+
| a|[[a,1], [c,2]]|
| b| null|
| c|[[a,1], [c,2]]|
+---+--------------+
答案 1 :(得分:1)
可以使用内置SQL函数array_contains
:
import org.apache.spark.sql.functions._
df1.join(df2, expr("array_contains(list.id, id)"), "left")
注意:您可能想尝试直接使用org.apache.spark.sql.functions.array_config
(不是在expr
的调用中,即df1.join(df2, array_contains($"list.id", $"id"), "left")
),但是赢了&# 39;在这种情况下,因为它的签名将其用法限制在第二个参数是某个常量值的情况下(期望Any
但是如果参数的类型是Column
则失败)。 / p>
答案 2 :(得分:1)
在explode
上使用join
和id
第一个数据框:
df2.withColumn("obj", explode($"list_obj")).
join(df1, $"obj.id" === $"id", "right")