如何获取PySpark列中缺失值的数值并删除全缺失列?
PySpark处理OpenFoodFacts数据集:获取缺失值数值并删除全缺失列
一、一次性获取所有列的缺失值具体数值
不用循环逐列查询,通过一次聚合操作就能拿到所有列的缺失值(包含null和nan)数量,结果转成字典后可直接读取具体数值:
from pyspark.sql.functions import col, isnan, when, count # 聚合计算所有列的缺失值数量 missing_count_dict = data.agg( *[count(when(isnan(c) | col(c).isNull(), c)).alias(c) for c in data.columns] ).collect()[0].asDict() # 遍历打印各列缺失值数量 for col_name, missing_num in missing_count_dict.items(): print(f"列 {col_name} 的缺失值数量: {missing_num}")
这段代码通过agg一次性完成所有列的缺失值统计,collect()[0]获取统计结果的唯一行数据,asDict()将其转为字典,方便直接提取每列的缺失值具体数值。
二、高效删除全缺失值列
基于上面得到的缺失值统计结果,结合数据集总行数,筛选出缺失值数量等于总行数的列,然后批量删除,避免多次触发Spark作业:
total_row_num = data.count() # 筛选出全缺失的列 cols_to_remove = [col for col, num in missing_count_dict.items() if num == total_row_num] # 批量删除目标列 cleaned_data = data.drop(*cols_to_remove) cleaned_data.show()
这种方式仅触发两次Spark作业(一次统计缺失值、一次统计总行数),远优于循环逐列处理的低效方案。
三、原代码问题分析
第一段代码无效原因:
data.select([count(when(isnan(c) | col(c).isNull(), c))])返回的是DataFrame对象,直接和整数data.count()比较永远为False,自然不会删除任何列。需要先提取DataFrame中的具体数值(比如collect()[0][0])再进行比较。第二段代码耗时过长原因:
循环逐列执行filter(...).count()会触发大量独立的Spark作业(每列一次),列数量较多时会导致任务堆积、耗时剧增。另外这段代码仅判断了null,未覆盖数值类型列的nan情况,判断逻辑不完整。
内容的提问来源于stack exchange,提问作者AWDn0n
相关产品推荐
相关产品推荐

