Spark Scala如何用数组或其他DataFrame的值替换DataFrame null值
实现方案
核心思路:为原表中deptid为null的记录、待填充的deptid值列表分别生成一一对应的连续行号,通过行号做等值关联后完成值填充,完全匹配你「数组长度和null值数量一致、不强制要求emp和deptid对应关系」的前提。
完整Scala Spark代码
import org.apache.spark.sql.expressions.Window import org.apache.spark.sql.functions._ import spark.implicits._ // 原始员工DataFrame val emp = Seq( (163L, null), (843L, null) ).toDF("empID", "deptid") // 待填充的deptid数组 val range = Array(20L, 21L) // 1. 给原表中deptid为null的行生成从0开始的连续行号,非null行行号置空 val empWindow = Window.partitionBy(col("deptid").isNull).orderBy("empID") val empWithRn = emp.withColumn( "rn", when(col("deptid").isNull, row_number().over(empWindow) - 1) ) // 2. 将待填充数组转为DataFrame,同样生成从0开始的连续行号 val fillDf = range.toSeq.toDF("fill_deptid") .withColumn("rn", row_number().over(Window.orderBy("fill_deptid")) - 1) // 3. 按行号左关联,用填充值替换null位,删除辅助列 val result = empWithRn .join(fillDf, Seq("rn"), "left") .withColumn("deptid", coalesce(col("deptid"), col("fill_deptid"))) .drop("rn", "fill_deptid")
执行result.show()即可得到预期输出:
+-----+------+ |empID|deptid| +-----+------+ | 163| 20| | 843| 21| +-----+------+
说明
- 窗口的排序字段可任意选择,由于你不要求empID和填充值的绑定关系,只要保证null行的行号连续、和填充列表的行号一一对应即可
- 方案兼容原表存在非null deptid的场景,已有非null值不会被覆盖,仅填充null位置
- 之前直接join两个表得到错误结果,是因为没有设置唯一的关联匹配键,无规则连接会产生笛卡尔积或外连接空行,通过行号做关联键可以实现null行和填充值的一对一匹配
内容的提问来源于stack exchange,提问作者amateur-coder
相关产品推荐
相关产品推荐

