You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySpark DataFrame基于条件前向填充问题:filled与filled1结果相同原因

PySpark 仅在flag=1时实现前向填充的问题解析与解决方法

问题原因

你当前的代码逻辑没有实现「仅当flag=1时触发前向填充,后续flag=0的行沿用最近的flag=1对应的salary」的需求,导致filled和filled1结果一致,核心问题点:

  • 原代码中when(col("flag") == 1, last(col("salary"), True).over(window))里的last(salary),在当前窗口(从分区开头到当前行)中,当flag=1时,当前行的salary就是窗口内最后一个非空值,返回结果和当前行的salary完全相同;而otherwise(col("salary"))直接取原salary。所以无论flag是0还是1,filled列最终都是原salary,和直接取全局last的filled1自然没有区别。
  • 你的真实需求是把flag=1的salary作为「填充锚点」,后续flag=0的行需要继承最近的这个锚点值,但原代码没有对锚点值进行跨行传递的逻辑。

解决方法

要实现需求,需要先标记出flag=1的锚点salary,再对锚点值做前向填充,最后合并原salary和填充值:

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, when, last
from pyspark.sql.window import Window

spark = SparkSession.builder.getOrCreate()

data = [("person1", "1", 100, 0),
        ("person1", "2", 1000, 1),
        ("person1", "3", 1000, 0),
        ("person2", "1", 5, 0),
        ("person2", "2", 5, 0),
        ("person2", "3", 3, 0),
        ("person2", "4", 10, 1),
        ("person2", "5", 10, 0)]

df = spark.createDataFrame(data, ["person", "date", "salary", "flag"])

# 定义窗口:按person分区,按date排序,窗口范围从开头到当前行
window = Window.partitionBy("person").orderBy("date").rowsBetween(Window.unboundedPreceding, Window.currentRow)

# 创建临时列:仅flag=1时保留salary,其余为null
df = df.withColumn("flagged_salary", when(col("flag") == 1, col("salary")))

# 对flagged_salary做前向填充,取最近的非null值(即最近的flag=1的salary)
df = df.withColumn("filled", last(col("flagged_salary"), ignorenulls=True).over(window))

# 最终填充逻辑:如果filled有值(即存在之前的flag=1锚点)则用filled,否则用原salary
df = df.withColumn("final_filled", when(col("filled").isNotNull(), col("filled")).otherwise(col("salary")))

df.select("person", "date", "salary", "flag", "final_filled").show()

输出结果

+-------+----+------+----+-----------+
| person|date|salary|flag|final_filled|
+-------+----+------+----+-----------+
|person1|   1|   100|   0|        100|
|person1|   2|  1000|   1|       1000|
|person1|   3|  1000|   0|       1000|
|person2|   1|     5|   0|          5|
|person2|   2|     5|   0|          5|
|person2|   3|     3|   0|          3|
|person2|   4|    10|   1|         10|
|person2|   5|    10|   0|         10|
+-------+----+------+----+-----------+

如果你的需求是「flag=0时,如果之前有flag=1的记录就填充,否则保持原salary;flag=1时保持原salary」,上述代码完全符合。如果需要调整逻辑(比如flag=0且无锚点时设为null),可以修改最后一步的when条件。

内容的提问来源于stack exchange,提问作者Henri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 07:17:52