PySpark中前向填充缺失数据失效问题排查
解决PySpark窗口函数填充Null值无效的问题
我猜你大概率是窗口定义或者填充函数的参数没搞对——这种用最近的非空值填充Null的需求,核心是要用到last()/first()函数,并且必须加上ignoreNulls=True这个关键参数,同时窗口的范围也要设置正确!
先看你的原始数据集:
| id | name | country | languages |
|---|---|---|---|
| 1 | Bob | USA | Spanish |
| 2 | Angelina | France | null |
| 3 | Carl | Brazil | null |
| 4 | John | Australia | English |
| 5 | Anne | Nepal | null |
常见错误原因
你之前的代码可能犯了这两个错误之一:
- 没加
ignoreNulls=True:默认情况下last()会包含Null值,遇到Null行时,取到的还是当前行的Null - 窗口范围设置错误:比如用了默认的窗口(只包含当前行),那
last()只能取当前行的值,自然不会填充
正确实现代码
下面是可以正常生效的完整可复现示例:
from pyspark.sql import SparkSession from pyspark.sql.window import Window from pyspark.sql.functions import last # 初始化SparkSession spark = SparkSession.builder.appName("FillNullWithLastNonEmpty").getOrCreate() # 构建你的数据集 data = [ (1, "Bob", "USA", "Spanish"), (2, "Angelina", "France", None), (3, "Carl", "Brazil", None), (4, "John", "Australia", "English"), (5, "Anne", "Nepal", None) ] df = spark.createDataFrame(data, ["id", "name", "country", "languages"]) # 定义窗口:按id排序,范围从第一行到当前行(能拿到当前行之前所有行的最后一个非空值) fill_window = Window.orderBy("id").rowsBetween(Window.unboundedPreceding, Window.currentRow) # 用last函数填充,关键是ignoreNulls=True df_filled = df.withColumn( "temp_filled_spark", last("languages", ignoreNulls=True).over(fill_window) ) # 查看结果 df_filled.show()
运行结果
执行后你会看到temp_filled_spark列已经正确填充了Null值:
| id | name | country | languages | temp_filled_spark |
|---|---|---|---|---|
| 1 | Bob | USA | Spanish | Spanish |
| 2 | Angelina | France | null | Spanish |
| 3 | Carl | Brazil | null | Spanish |
| 4 | John | Australia | English | English |
| 5 | Anne | Nepal | null | English |
拓展:如果需要向后填充(用下一个非空值填充前面的Null)
如果你的需求是反过来,用后面的非空值填充前面的Null,可以用first()函数,调整窗口范围:
# 定义向后填充的窗口 back_fill_window = Window.orderBy("id").rowsBetween(Window.currentRow, Window.unboundedFollowing) df_back_filled = df.withColumn( "temp_back_filled", first("languages", ignoreNulls=True).over(back_fill_window) )
内容的提问来源于stack exchange,提问作者user8907896
相关产品推荐
相关产品推荐

