Spark/Scala:如何一次性过滤DataFrame中含NaN的行?
解决Spark DataFrame无法过滤含NaN/空值行的问题
嘿,我之前也碰到过一模一样的情况!df.na.drop()没生效,大概率是因为你的数据里的「空值」并不是Spark默认识别的null或数值类型的NaN,而是空字符串这类其他形式的空值——毕竟Spark的na.drop()默认只处理null和数值列的NaN,对空字符串完全没反应。
下面给你几个可行的解决步骤:
第一步:先确认空值的类型
首先得搞清楚你的数据里到底是什么类型的空值,才能针对性处理:
import org.apache.spark.sql.functions._ // 查看各列的非空计数,对比总行数(455)就能发现哪列有问题 df.describe().show() // 或者逐一检查列的空值情况,比如检查字符串列的空字符串+null,数值列的NaN+null df.filter(col("Kik").isNull || col("Kik") === "").count() // 检查字符串列 df.filter(col("某数值列").isNull || col("某数值列").isNaN).count() // 检查数值列
第二步:针对性过滤所有空值
根据第一步的结果,选择对应的处理方式:
方式一:先把空字符串转成null,再用na.drop()
如果你的数据里混合了空字符串、null和NaN,可以先把所有列的空字符串替换成null,再调用na.drop()一次性删除:
import org.apache.spark.sql.functions._ // 遍历所有列,将空字符串替换为null val dfWithNulls = df.select( df.columns.map(c => when(col(c) === "", null).otherwise(col(c)).alias(c)): _* ) // 删除所有含null/NaN的行 val cleanedDf = dfWithNulls.na.drop() cleanedDf.count()
方式二:自定义过滤条件,覆盖所有空值类型
如果需要更精准的控制,可以直接生成一个过滤条件,确保每一列都不为null、NaN(仅数值列)或空字符串:
import org.apache.spark.sql.functions._ // 生成过滤条件:每一列都要符合非空要求 val filterCondition = df.columns.map(c => { val colRef = col(c) // 数值列需要排除null和NaN,字符串列排除null和空串 if (df.schema(c).dataType.isInstanceOf[org.apache.spark.sql.types.NumericType]) { colRef.isNotNull && !colRef.isNaN } else { colRef.isNotNull && colRef =!= "" } }).reduce(_ && _) // 应用过滤条件 val cleanedDf = df.filter(filterCondition) cleanedDf.count()
额外提醒
Spark里的NaN只存在于Double/Float这类数值类型的列中,字符串列是没有NaN的,只有null和空字符串,所以处理字符串列的时候不用考虑isNaN哦~
内容的提问来源于stack exchange,提问作者Alina
相关产品推荐
相关产品推荐

