如何在Spark数据帧中执行链函数?

时间:2016-12-03 21:20:33

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

如何在Spark数据帧中执行链函数?在我的代码中,我想先做大写,然后做一个布尔转换。但是我的代码没有用。感谢

import org.apache.spark.sql.functions.udf
val trimStr: String => String = _.trim
val trimUDF = udf(trimStr)

import org.apache.spark.sql.functions.udf
val upperCaseStr: String => String = _.toUpperCase
val upperCaseUDF = udf(upperCaseStr)

import org.apache.spark.sql.functions.udf
     def booleanValueSubstitution = udf[String, String] {
       case "" => "N"
       case null => "N"           
       case "TRUE" => "Y"        
     }
var df= df1.withColumn("xx", booleanValueSubstitution(upperCaseUDF(df1("yy"))) )

1 个答案:

答案 0 :(得分:0)

首先不要重新发明轮子。对于许多常见任务,您可以找到内置函数:

import org.apache.spark.sql.functions.{trim, upper}

除了null安全之外,还有其他好处:

val df = Seq(None, Some(""), Some("true"), Some(" TRUE "), Some("foo")).toDF("x")

df.select(upper(trim($"x")))
+--------------+
|upper(trim(x))|
+--------------+
|          null|
|              |
|          TRUE|
|          TRUE|
|           foo|
+--------------+

您定义的函数({1}}除外)不是。每次你的代码遇到booleanValueSubstitution时,它都会因NPE而失败,所以如果你决定重新发明轮子,你应该总是为此做好准备。

您可以像对NULL一样进行模式匹配,也可以使用booleanValueSubstitution

Try

如果您决定使用模式匹配,请确保条件是详尽无遗的:

import scala.util.Try

val upperCaseUDF = udf((s: String) => Try(s.toUpperCase).toOption)
val trimUDF = udf((s: String) => Try(s.trim).toOption)

或更简单:

val booleanValueSubstitution = udf[String, String] {
  case "" => "N"
  case null => "N"           
  case "TRUE" => "Y"   
  case _ => "N"
}

否则你会得到val booleanValueSubstitution = udf[String, String] { case "TRUE" => "Y" case _ => "N" }

接下来,您可以使用惯用的SQL解决方案代替与scala.MatchError的模式匹配。例如,您可以使用udf

CASE WHEN

或:

import org.apache.spark.sql.functions.{when, coalesce, lit}

df.select(
  when($"x".isNull, "N").when($"x" === "", "N").when($"x" === "TRUE", "Y")
)

最后,如果你认为布尔值,最好使用布尔值:

df.select(coalesce(when($"x" === "TRUE", "Y").otherwise("N"), lit("N")))

一般来说:

  • 由于多种原因,内置函数通常比UDF更受欢迎。
  • 不允许在每个位置使用UDF,因此并不总是可以进行链接。在某些情况下,您必须单独添加when($"x".isNull, false).when($"x" === "", false).otherwise(true) 结果:

    udf