如何在Spark DataFrame中删除含缺失数据的行列,解决na.drop不生效问题
问题原因
Spark的na.drop()默认仅识别、删除包含原生null或NaN的行。你的数据集使用自定义标记M、空字符串表示缺失值,且原本应为数值类型的字段全部定义为String类型,na.drop()无法识别这类自定义缺失标记,因此执行后仍会出现带M的行。
高效清洗方案
按以下步骤处理即可,全程为Spark分布式操作,无性能瓶颈:
- 批量替换所有数值列中的自定义缺失标记为Spark可识别的
null - 将数值列转换为对应数值类型,避免后续聚合运算返回字符结果
- 按需删除含空值的行,指定扫描列范围可进一步提升执行效率
Scala版本实现
import org.apache.spark.sql.functions.col import org.apache.spark.sql.functions.when // 定义需要处理的数值列,可根据实际业务调整清单 val numericCols = List( "Visibility", "DryBulbFarenheit", "DryBulbCelsius", "WetBulbFarenheit", "WetBulbCelsius", "DewPointFarenheit", "DewPointCelsius", "RelativeHumidity", "WindSpeed", "WindDirection", "StationPressure", "SeaLevelPressure", "HourlyPrecip", "Altimeter" ) // 第一步:替换自定义缺失标记为null val processedDf = numericCols.foldLeft(weathers_df) { (df, colName) => df.withColumn(colName, when(col(colName).isin("M", "", " "), null).otherwise(col(colName))) } // 第二步:转换为Double数值类型,转换失败的异常值也会自动转为null val typedDf = numericCols.foldLeft(processedDf) { (df, colName) => df.withColumn(colName, col(colName).cast("Double")) } // 第三步:删除数值列包含空值的行,指定subset参数避免扫描全列,效率更高 val cleanedDf = typedDf.na.drop(subset = numericCols)
PySpark版本实现
from pyspark.sql.functions import col, when # 定义需要处理的数值列,可根据实际业务调整清单 numeric_cols = [ "Visibility", "DryBulbFarenheit", "DryBulbCelsius", "WetBulbFarenheit", "WetBulbCelsius", "DewPointFarenheit", "DewPointCelsius", "RelativeHumidity", "WindSpeed", "WindDirection", "StationPressure", "SeaLevelPressure", "HourlyPrecip", "Altimeter" ] # 第一步:替换自定义缺失标记为null processed_df = weathers_df for col_name in numeric_cols: processed_df = processed_df.withColumn(col_name, when(col(col_name).isin(["M", "", " "]), None).otherwise(col(col_name))) # 第二步:转换为Double数值类型,转换失败的异常值也会自动转为null typed_df = processed_df for col_name in numeric_cols: typed_df = typed_df.withColumn(col_name, col(col_name).cast("double")) # 第三步:删除数值列包含空值的行,指定subset参数避免扫描全列,效率更高 cleaned_df = typed_df.na.drop(subset=numeric_cols)
补充说明
- 若需要将样例中表示微量降水的
T也判定为缺失值,只需将"T"添加到isin的参数列表中即可 - 若允许部分数值列为空,调整
numeric_cols清单和na.drop的subset参数即可 - 转换为数值类型后,再执行min、max等聚合运算将返回正常数值结果,不会再出现字符
M
内容的提问来源于stack exchange,提问作者WallyWorld
相关产品推荐
相关产品推荐

