如何在PySpark DataFrame中按分组变量统计指定列的零值占比
PySpark实现分组统计零值占比与均值聚合
你可以通过PySpark的分组聚合结合条件判断来实现需求,核心是计算每组的零值数量、总记录数推导占比,同时直接计算均值。具体实现如下:
完整代码示例
首先导入PySpark SQL函数库:
from pyspark.sql import functions as F
然后执行分组聚合操作:
result_df = ( df # 按指定字段分组,排除Date .groupBy("source_cd", "Day", "hour", "five_min_block") .agg( # 统计分组总记录数 F.count("*").alias("total_records"), # 统计零值记录数:标记零值为1、非零为0,求和得到零值数量 F.sum(F.when(F.col("five_min_block_volume") == 0, 1).otherwise(0)).alias("zero_count"), # 计算five_min_block_volume的均值 F.avg("five_min_block_volume").alias("avg_volume") ) # 计算零值占比,保留两位小数转为百分比 .withColumn( "zero_ratio", F.round((F.col("zero_count") / F.col("total_records")) * 100, 2) ) # 可选:处理极端情况,避免分组无记录时除以零错误 # .withColumn( # "zero_ratio", # F.round(F.coalesce((F.col("zero_count") / F.col("total_records")) * 100, F.lit(0)), 2) # ) # 可选:将占比格式化为带%的字符串,比如40.00% # .withColumn("zero_ratio", F.concat(F.col("zero_ratio"), F.lit("%"))) )
代码说明
groupBy:严格按照你指定的4个字段分组,排除Date;count("*"):统计每个分组的总记录条数;sum(when(...)):通过条件判断给零值记录标记为1,非零标记为0,求和后直接得到该分组的零值数量;avg():直接调用内置函数计算目标列的均值;withColumn计算zero_ratio:用零值数除以总记录数,乘以100转为百分比,round函数控制小数位数;- 注释部分的
coalesce用来处理极端场景(比如分组无记录时避免除以零报错),如果你的数据每个分组都有有效记录可以忽略; - 最后可选的字符串拼接可以把占比格式化为更直观的百分比文本。
执行后,result_df会包含每个分组的总记录数、零值数、均值和零值占比,完全匹配你的需求。
内容的提问来源于stack exchange,提问作者viv1993
相关产品推荐
相关产品推荐

