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

PySpark:如何使用首个非空值与最后一个非空值实现DataFrame列的Coalesce操作

用PySpark填充首尾空值:首非空值填前,尾非空值填后

这个需求我之前也遇到过,其实拆解开来两步就能搞定——先拿到首尾的非空基准值,再根据位置判断填充就行。我给你一步步演示,用你描述的场景来举例:

1. 先创建示例DataFrame

先模拟你提到的有首尾空值的DataFrame:

from pyspark.sql import SparkSession
from pyspark.sql import functions as F

# 初始化SparkSession(如果还没初始化的话)
spark = SparkSession.builder.appName("FillNulls").getOrCreate()

# 创建示例数据
df = spark.createDataFrame(
    [
        (1, None),
        (2, None),
        (3, 0.6),
        (4, 1.2),
        (5, 3.0),
        (6, None),
        (7, None)
    ],
    ["id", "value"]
)

df.show()

输出的原始数据:

+---+-----+
| id|value|
+---+-----+
|  1| null|
|  2| null|
|  3|  0.6|
|  4|  1.2|
|  5|  3.0|
|  6| null|
|  7| null|
+---+-----+

2. 获取首尾非空基准值

首先拿到value列的第一个非空值和最后一个非空值,这里要注意用ignorenulls=True来跳过空值:

# 获取首个非空值
first_non_null = df.agg(F.first("value", ignorenulls=True)).first()[0]
# 获取最后一个非空值
last_non_null = df.agg(F.last("value", ignorenulls=True)).first()[0]

这里first_non_null会是0.6,last_non_null会是3.0。

3. 确定首尾非空值的位置

接下来需要知道第一个非空值出现在哪一行,最后一个非空值出现在哪一行(假设id是按顺序排列的行标识,如果你的DataFrame没有自增id,可以用monotonically_increasing_id()生成临时顺序列):

# 获取第一个非空值的最小id(最早出现的位置)
first_pos = df.agg(F.min(F.when(F.col("value").isNotNull(), F.col("id")))).first()[0]
# 获取最后一个非空值的最大id(最晚出现的位置)
last_pos = df.agg(F.max(F.when(F.col("value").isNotNull(), F.col("id")))).first()[0]

4. 填充空值

最后用when...otherwise逻辑判断填充:

filled_df = df.withColumn(
    "filled_value",
    F.when(
        # 第一个非空值之前的行,用首非空值填充
        F.col("id") < first_pos,
        first_non_null
    ).when(
        # 最后一个非空值之后的行,用尾非空值填充
        F.col("id") > last_pos,
        last_non_null
    ).otherwise(
        # 中间的行保留原数据
        F.col("value")
    )
)

filled_df.show()

最终输出的结果:

+---+-----+------------+
| id|value|filled_value|
+---+-----+------------+
|  1| null|         0.6|
|  2| null|         0.6|
|  3|  0.6|         0.6|
|  4|  1.2|         1.2|
|  5|  3.0|         3.0|
|  6| null|         3.0|
|  7| null|         3.0|
+---+-----+------------+

补充:如果没有自增id怎么办?

如果你的DataFrame没有类似id的顺序列,可以用monotonically_increasing_id()生成一个临时的顺序列来判断位置:

df_with_temp_id = df.withColumn("temp_id", F.monotonically_increasing_id())
# 之后的步骤用temp_id代替id即可,最后记得删掉临时列

边缘情况提醒

如果整个列全是空值,那first_non_null和last_non_null都会是None,填充后还是空值,这种情况可以根据你的业务需求额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:37:32