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

如何在PySpark DataFrame分组后聚合多个字符串列?

解决方案:PySpark分组聚合多类型列并消除空值

问题场景

你有一个包含字符串(string)和数值(double)类型列的PySpark DataFrame,结构如下:

+---+---+--------+-----+------+----+
|tin|ecu|DcyStart|did1 |did2  |did3|
+---+---+--------+-----+------+----+
|1  |1  |1       |34   |null  |null|
|1  |1  |2       |null |2     |null|
|1  |1  |3       |null |null  |b   |
|1  |1  |4       |null |null  |null|
|1  |2  |1       |40   |null  |null|
|1  |2  |2       |null |2     |null|
|1  |2  |3       |null |null  |f   |
|1  |2  |4       |null |null  |null|
+---+---+--------+----+-------+----+

需求是:

  • 移除DcyStart列
  • 按tin和ecu分组,每个did列保留任意一个非空值(部分列可能有多行非空,取任意即可)
  • 处理100+个did列,避免手动逐个编写逻辑

之前尝试用first()、max()等聚合函数时遇到两个问题:聚合函数无法处理字符串类型、聚合函数不能直接接收多列参数。

解决方法

核心思路是对每个did列单独应用支持多类型的聚合函数,并跳过空值,利用列表推导式批量生成聚合逻辑,无需手动处理每一列。

步骤1:导入PySpark函数库

from pyspark.sql import functions as F

步骤2:定义需要聚合的列列表

list_of_dids = ["did1", "did2", "did3"]  # 替换为你的100+列名称列表

步骤3:批量生成聚合表达式

使用first()函数并设置ignorenulls=True,该函数支持字符串和数值类型,会自动跳过空值,取第一个非空值(符合"任意非空值"的需求):

agg_exprs = [F.first(col, ignorenulls=True).alias(col) for col in list_of_dids]

步骤4:执行分组聚合

# 先移除不需要的DcyStart列,再分组聚合
result = data.drop("DcyStart").groupBy("tin", "ecu").agg(*agg_exprs)

验证结果

执行后得到的DataFrame结构如下:

+---+----+-----+----+----+
|tin|ecu |did1 |did2|did3|
+---+----+-----+----+----+
|1  |1   |34   |2   |b   |
|1  |2   |40   |2   |f   |
+---+----+-----+----+----+

为什么之前的代码出错?

你之前的写法data.groupBy("tin", "ecu").first(*list_of_dids)存在两个问题:

  1. first()方法直接调用在GroupedData对象上时,不带参数是取每组的第一行完整数据,不能直接传入多列参数;
  2. 未设置ignorenulls=True,导致空值被优先返回,且未针对每个列单独处理聚合逻辑。

可选替代方案

如果部分列需要取其他规则的非空值(比如字符串取字典序最大/最小值),可以替换聚合函数:

  • 数值类型:F.max(col)、F.min(col)
  • 字符串类型:F.max(col)(取字典序最大)、F.min(col)(取字典序最小)
    只需修改聚合表达式即可:
# 示例:用max()替代first()
agg_exprs = [F.max(col).alias(col) for col in list_of_dids]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:55:27