如何在PySpark中统计多列所有唯一值组合的计数
问题场景
现有结构如下的PySpark DataFrame:
---------------------------- id A B C id1 on on on id1 on off on id1 on on on id1 on on on id1 on on off -----------------------------
需要实现两个层面的统计需求:
- 基础需求:查找指定列的所有唯一值组合,统计每个组合的出现次数,针对示例中id+A+B+C的列组合,期望输出为:
---------------------------- id A B C count id1 on on on 3 id1 on off on 1 id1 on on off 1 ----------------------------- - 扩展需求:获取所有列的全部可能维度组合的统计结果(比如A/B组合、A/C组合、单A列、单B列等所有维度子集的计数),由于涉及列数超过10个,需要无需逐一对不同列组合手动编写group by逻辑的一次性实现方案。
实现方法
单组固定列组合统计
针对明确指定列组合的计数需求,直接调用原生groupBy配合count聚合即可,代码如下:
# 传入需要统计组合的列名即可 result = df.groupBy("id", "A", "B", "C").count() result.show()
执行后返回结果和示例期望完全匹配。
全维度组合一次性统计
针对需要输出所有列可能组合计数的场景,直接使用PySpark内置的cube聚合算子,该算子会自动计算传入列的所有可能维度组合的聚合结果,无需手动枚举列组合编写group by,10个维度列的场景下性能远高于循环执行分组统计。
提示:如果只需要统计固定前缀的层级维度组合(比如所有组合必须包含id列),可以替换为
rollup算子;如果需要任意维度的自由组合统计,使用cube即可。
参考实现代码:
from pyspark.sql.functions import col, count # 定义固定保留的分组列、需要做全组合的维度列 fixed_dim = "id" combine_dims = ["A", "B", "C"] # 一次性计算所有维度组合的计数 all_dim_result = df.cube(fixed_dim, *combine_dims).agg(count("*").alias("count")) # 可根据需要过滤无效行,比如过滤掉固定维度为空的全局统计行 all_dim_result = all_dim_result.filter(col(fixed_dim).isNotNull()) all_dim_result.show()
返回结果中,列值为null代表该列未参与当前行的分组统计:
- 当A、B、C三列值均非空时,对应该三列+id的全维度组合计数,和单组groupBy的结果一致
- 当某一维度列为null时,代表当前行统计时排除了该维度,比如B列为null、A/C列非空时,对应该行是id+A+C维度组合的计数
- 当A、B、C列均为null时,对应id维度的总计数,示例中id1对应的计数值为5
如果需要快速筛选特定维度组合的结果,可以在结果上直接加过滤条件即可,不需要调整聚合逻辑。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

