Spark 将 DataFrame API 中的所有 NaN 替换为 null

Rap*_*oth 2 scala apache-spark spark-dataframe

我有一个包含许多双(和/或浮点)列的数据框,其中确实包含 NaN。我想用空值替换所有 NaN(即 Float.NaN 和 Double.NaN)。

我可以用例如单列来做到这一点x

val newDf = df.withColumn("x", when($"x".isNaN,lit(null)).otherwise($"x"))
Run Code Online (Sandbox Code Playgroud)

这有效,但我想一次对所有列执行此操作。我最近发现DataFrameNAFunctions( df.na)fill听起来正是我需要的。不幸的是我没有做到以上几点。 fill应该用给定的值替换所有 NaN 和空值,所以我这样做:

df.na.fill(null.asInstanceOf[java.lang.Double]).show
Run Code Online (Sandbox Code Playgroud)

这给了我一个 NullpointerException

还有一个很有前途的replace方法,但我什至无法编译代码:

df.na.replace("x", Map(java.lang.Double.NaN -> null.asInstanceOf[java.lang.Double])).show
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这给了我

Error:(57, 34) type mismatch;
 found   : scala.collection.immutable.Map[scala.Double,java.lang.Double]
 required: Map[Any,Any]
Note: Double <: Any, but trait Map is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
    df.na.replace("x", Map(java.lang.Double.NaN -> null.asInstanceOf[java.lang.Double])).show
Run Code Online (Sandbox Code Playgroud)

him*_*ian 5

null在 Spark 中替换所有 NaN(s),您只需Map为每一列创建一个替换值,如下所示:

val map = df.columns.map((_, "null")).toMap
Run Code Online (Sandbox Code Playgroud)

然后您可以使用fill空值替换 NaN(s) :

df.na.fill(map)
Run Code Online (Sandbox Code Playgroud)

例如:

scala> val df = List((Float.NaN, Double.NaN), (1f, 0d)).toDF("x", "y")
df: org.apache.spark.sql.DataFrame = [x: float, y: double]

scala> df.show
+---+---+
|  x|  y|
+---+---+
|NaN|NaN|
|1.0|0.0|
+---+---+

scala> val map = df.columns.map((_, "null")).toMap
map: scala.collection.immutable.Map[String,String] = Map(x -> null, y -> null)

scala> df.na.fill(map).printSchema
root
 |-- x: float (nullable = true)
 |-- y: double (nullable = true)


scala> df.na.fill(map).show
+----+----+
|   x|   y|
+----+----+
|null|null|
| 1.0| 0.0|
+----+----+
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助 !

  • 谢谢,但我仍在苦苦思索为什么当您将“null”定义为字符串字面量时,这会起作用,这一定是某种内在魔法吗? (5认同)