如何连接两个含数组列的DataFrame?其一数组元素可空,另一不可
嘿,我来帮你搞定这个包含数组列的DataFrame连接问题!先理清楚咱们的场景:df1的Index列是元素完全非空的数组,而df2的Index列允许元素为空,现在要基于这两个数组列把两个表连起来对吧?下面给你两种实用的解决方案,你可以根据自己的需求选择:
方案1:直接用数组列做等值Join(简单直接,适用于Spark 2.3+)
Spark从2.3版本开始已经支持数组的等值比较了,只要两个数组的元素顺序、值完全匹配(注意:如果df2的数组里有null元素,而df1对应位置是非null,这俩数组会被判定为不相等,这类行就不会被匹配上),直接写join就行:
val joinedDF = df1.join(df2, df1("Index") === df2("Index"), "inner")
这种方法适合你需要严格匹配的场景——只有当两个数组的每个对应元素都完全相等(包括null的情况:比如df2的数组是[1,null],df1的是[1,1],这俩就不匹配)。
方案2:自定义UDF灵活处理匹配规则(适配null元素的特殊需求)
如果你的需求更灵活,比如想把df2里的null元素视为和df1的对应元素相等,或者有其他自定义的匹配逻辑,那写个自定义UDF就最合适了:
import org.apache.spark.sql.functions.udf // 自定义一个判断数组是否匹配的UDF,规则可以自己改 val arraysMatch = udf((arr1: Array[Int], arr2: Array[Int]) => { // 先处理数组本身为null的情况 if (arr1 == null || arr2 == null) false // 数组长度不一样直接不匹配 else if (arr1.length != arr2.length) false // 逐元素比较:这里的规则是,要么元素相等,要么df2的元素是null(你可以按需调整) else arr1.zip(arr2).forall { case (val1, val2) => val1 == val2 || val2 == null } }) // 用这个UDF做连接条件 val joinedDF = df1.join(df2, arraysMatch(df1("Index"), df2("Index")), "inner")
小提示:
你可以根据自己的实际需求修改UDF里的匹配规则,比如:
- 要是想忽略某个方向的null(不过你的df1元素是不可为空的,这个可能用不上)
- 或者要求只有当两个元素都不为null且相等时才匹配,那把逻辑改成
val1 == val2 && val1 != null && val2 != null就行
另外,如果df2的整个Index列可能为null(不是元素null),UDF里的arr2 == null判断已经帮你处理了,不会出现空指针问题~
内容的提问来源于stack exchange,提问作者Chuang
相关产品推荐
相关产品推荐

