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

如何高效获取Spark DataFrame中所有分类变量的频率?支持单次表扫描

高效实现Spark DataFrame多分类变量频率统计(单次表扫描)

核心思路

借助Spark的stack函数将多列分类变量宽表转长表(unpivot),之后仅需一次分组聚合即可完成所有变量的频率统计,全程仅触发一次表扫描,彻底解决遍历列多次扫表的性能问题。

代码实现

假设源DataFrame名为df,具体代码如下:

import org.apache.spark.sql.functions._

// 定义需要统计的分类列列表
val catCols = List("FRUIT", "COLOR")

// 构造stack函数参数:每个列对应(列名常量, 列值)的组合
val stackExpr = catCols.map(col => s"'${col}', ${col}").mkString("stack(", ",", ") as (COLUMN, LEVEL)")

// 执行宽表转长表 + 分组聚合
val result = df.selectExpr(stackExpr)
  .groupBy("COLUMN", "LEVEL")
  .agg(count("*").alias("COUNT"))
  .orderBy("COLUMN", "LEVEL")

result.show()

代码细节说明

  • stack(n, expr1, expr2, ...):其中n是分类列的数量,每个'列名', 列名组合会将原表的一行拆分为一行新数据,最终把多列分类变量合并为COLUMN(原列名)和LEVEL(分类值)两列。
  • 分组聚合阶段,按COLUMN和LEVEL分组统计行数,直接得到对应分类的出现频率,全程仅扫描源表一次。

测试验证

用你提供的源数据测试:
源DataFrame内容:

FRUIT  COLOR
Apple  Red
Apple  Red
Apple  Yellow
Pear   Yellow
Pear   Yellow

执行代码后输出结果:

+------+------+-----+
|COLUMN| LEVEL|COUNT|
+------+------+-----+
| FRUIT| Apple|    3|
| FRUIT|  Pear|    2|
| COLOR|   Red|    2|
| COLOR|Yellow|    3|
+------+------+-----+

完全匹配期望输出。

扩展提示

如果需要处理空值,可在selectExpr后添加.filter(col("LEVEL").isNotNull)过滤空值行;即使分类列数量很多,该方法依然保持单次表扫描的高效性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:18:27