Scala Spark用NULL替换空字符串

时间:2018-09-24 17:57:27

标签: scala apache-spark apache-spark-sql

我要在此处将特定列中的值替换为null(如果它为空String)。

原因是我正在使用org.apache.spark.sql.functions.coalesce来填充基于另一个列的Dataframe列中的一个,但是我注意到某些行中的值是empty String而不是null,所以coalesce功能无法正常工作。

val myCoalesceColumnorder: Seq[String] = Seq("xx", "yy", "zz"),

val resolvedDf = df.select(
   df("a"),
   df("b"),
   lower(org.apache.spark.sql.functions.coalesce(myCoalesceColumnorder.map(x => adjust(x)): _*)).as("resolved_id")
)

在上面的示例中,我希望首先在列resolved_id中填充xx,如果它不为null,并且如果列yy为null,以此类推。但是由于有时xx列填充了""而不是null,所以我在'resolved_id'中得到了""

我尝试用

修复它
resolvedDf.na.replace("resolved_id", Map("" -> null))

但是根据na.replace文档,它仅在键和值均为BoleanStringDouble时才有效,所以我不能使用null在这里。

由于性能问题,我不想使用 UDF ,我只想知道是否还有其他技巧可以解决此问题?

我可以解决此问题的另一种方法是使用when,但不确定性能

resolvedDf
      .withColumn("resolved_id", when(col("resolved_id").equalTo(""), null).otherwise(col("resolved_id")))

1 个答案:

答案 0 :(得分:0)

这是性能更好的正确方法
resolvedDf.withColumn("resolved_id", when($"resolved_id" !== "", $"resolved_id"))

基本上不需要使用otherwise方法。

您可以检查来源::: https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/Column.scala#L507

/**
   * Evaluates a list of conditions and returns one of multiple possible result expressions.
   * If otherwise is not defined at the end, null is returned for unmatched conditions.
   *
   * {{{
   *   // Example: encoding gender string column into integer.
   *
   *   // Scala:
   *   people.select(when(people("gender") === "male", 0)
   *     .when(people("gender") === "female", 1)
   *     .otherwise(2))
   *
   *   // Java:
   *   people.select(when(col("gender").equalTo("male"), 0)
   *     .when(col("gender").equalTo("female"), 1)
   *     .otherwise(2))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def when(condition: Column, value: Any): Column = this.expr match {
    case CaseWhen(branches, None) =>
      withExpr { CaseWhen(branches :+ ((condition.expr, lit(value).expr))) }
    case CaseWhen(branches, Some(_)) =>
      throw new IllegalArgumentException(
        "when() cannot be applied once otherwise() is applied")
    case _ =>
      throw new IllegalArgumentException(
        "when() can only be applied on a Column previously generated by when() function")
  }