PySpark DataFrame空值填充问题:如何向下复制非空列值?
Spark DataFrame 非空值向下填充空记录的正确实现
你当前代码的问题在于使用lag函数只能获取当前行的前一行数据,遇到连续空值时,第二个空值的lag结果还是空,因此只能填充第一条空记录,无法完成连续向下填充的需求。
要实现连续向下填充,应该用last函数配合窗口,并设置ignoreNulls=True,这样窗口内会一直保留最近的非空值,直到遇到新的非空值为止。以下是完整的实现代码:
from pyspark.sql import SparkSession, functions as F from pyspark.sql.window import Window # 初始化SparkSession spark = SparkSession.builder.appName("FillDownExample").getOrCreate() data = [(8194, 'Closed'), (8194, ''), (8194, ''), (8196, 'Draft'), (8196, ''), (8197, 'open'), (8197, ''), (8197, '')] base_df = spark.createDataFrame(data, ["id","status"]) # 把空字符串转为null,方便last函数识别并忽略 df = base_df.withColumn("status", F.when(F.col("status") == "", None).otherwise(F.col("status"))) # 定义窗口:按id分组,范围覆盖从分区起始行到当前行 window_spec = Window.partitionBy("id").rowsBetween(Window.unboundedPreceding, Window.currentRow) # 使用last函数填充,ignoreNulls=True会跳过空值,取最近的非空值 filled_df = df.withColumn("status", F.last("status", ignoreNulls=True).over(window_spec)) filled_df.show()
运行后输出结果:
+----+------+ | id|status| +----+------+ |8194|Closed| |8194|Closed| |8194|Closed| |8196| Draft| |8196| Draft| |8197| open| |8197| open| |8197| open| +----+------+
关键说明:
- 空字符串转null:
last函数的ignoreNulls参数仅识别null值,因此先将空字符串转为null,确保空值能被正确忽略。 - 窗口范围设置:窗口范围从分区的第一行到当前行,保证每一行都能获取到之前所有行中最近的非空值。
- last函数的作用:
last("status", ignoreNulls=True)会在窗口内跳过所有null值,始终保留最近的非空status值,从而实现连续向下填充。
内容的提问来源于stack exchange,提问作者Shashank
相关产品推荐
相关产品推荐

