Spark中如何仅在已知值之间填充DataFrame空值?
仅在已知值之间填充空值的实现方案
要实现仅在两个相同非空值之间填充空值(两端空值、不同非空值之间的空值保留为null),可以通过获取每行前后的非空值并判断是否相等来实现,具体步骤如下:
实现思路
- 按
ID分区,按Record降序排序(匹配示例数据的排列逻辑)。 - 分别获取每行前一个非空的Target值和后一个非空的Target值。
- 仅当当前行Target为空,且前后非空值相等时,填充该值;其他情况保持原Target值不变。
完整代码
import pyspark.sql.functions as F from pyspark.sql import Window localdf = spark.createDataFrame( sc.parallelize( [ [1, 24, None, None], [1, 23, None, None], [1, 22, 1, 1], [1, 21, None, 1], [1, 20, None, 1], [1, 19, 1, 1], [1, 18, None, None], [1, 17, None, None], [1, 16, 2, 2], [1, 15, None, None], [1, 14, None, None], [1, 13, 3, 3], ] ), ["ID", "Record", "Target", "ExpectedValue"], ) # 定义窗口:按ID分区,Record降序排列 # 向前窗口:获取当前行之前的最后一个非空Target w_forward = Window.partitionBy("ID").orderBy(F.desc("Record")).rowsBetween(Window.unboundedPreceding, -1) # 向后窗口:获取当前行之后的第一个非空Target w_backward = Window.partitionBy("ID").orderBy(F.desc("Record")).rowsBetween(1, Window.unboundedFollowing) # 添加前后非空值列 localdf = localdf.withColumn("prev_non_null", F.last("Target", ignorenulls=True).over(w_forward)) localdf = localdf.withColumn("next_non_null", F.first("Target", ignorenulls=True).over(w_backward)) # 执行填充逻辑 localdf = localdf.withColumn( "FilledTarget", F.when( F.col("Target").isNull() & F.col("prev_non_null").isNotNull() & F.col("next_non_null").isNotNull() & (F.col("prev_non_null") == F.col("next_non_null")), F.col("prev_non_null") ).otherwise(F.col("Target")) ) # 查看结果 localdf.orderBy("ID", F.desc("Record")).show()
输出结果
+---+------+------+-------------+------------+------------+------------+ | ID|Record|Target|ExpectedValue|prev_non_null|next_non_null|FilledTarget| +---+------+------+-------------+------------+------------+------------+ | 1| 24| NULL| NULL| NULL| 1| NULL| | 1| 23| NULL| NULL| NULL| 1| NULL| | 1| 22| 1| 1| NULL| 1| 1| | 1| 21| NULL| 1| 1| 1| 1| | 1| 20| NULL| 1| 1| 1| 1| | 1| 19| 1| 1| 1| 2| 1| | 1| 18| NULL| NULL| 1| 2| NULL| | 1| 17| NULL| NULL| 1| 2| NULL| | 1| 16| 2| 2| 1| 3| 2| | 1| 15| NULL| NULL| 2| 3| NULL| | 1| 14| NULL| NULL| 2| 3| NULL| | 1| 13| 3| 3| 2| NULL| 3| +---+------+------+-------------+------------+------------+------------+
可以看到FilledTarget列与ExpectedValue列完全匹配,实现了预期的填充逻辑。
内容的提问来源于stack exchange,提问作者John Stud
相关产品推荐
相关产品推荐

