Spark UDF作为函数参数,UDF不在函数范围

时间:2017-02-08 21:03:14

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

我有一些UDF,我希望将它作为函数参数与数据帧一起传递。

执行此操作的一种方法可能是在函数内创建UDF,但这会创建并销毁UDF的多个实例而不重用它,这可能不是解决此问题的最佳方法。

这是一段代码示例 -

val lkpUDF = udf{(i: Int) => if (i > 0) 1 else 0}

val df =   inputDF1
    .withColumn("new_col", lkpUDF(col("c1")))
val df2 =   inputDF2.
  .withColumn("new_col", lkpUDF(col("c1")))

我没有做上述事情,而是希望做到这样的事情 -

val lkpUDF = udf{(i: Int) => if (i > 0) 1 else 0}

def appendCols(df: DataFrame, lkpUDF: ?): DataFrame = {

    df
      .withColumn("new_col", lkpUDF(col("c1")))

  }
val df = appendCols(inputDF, lkpUDF)

上面的UDF非常简单,但在我的情况下,它可以返回基本类型或用户定义的case类类型。任何想法/指针将不胜感激。感谢。

1 个答案:

答案 0 :(得分:3)

具有相应签名的功能需要:

import org.apache.spark.sql.UserDefinedFunction

def appendCols(df: DataFrame, func: UserDefinedFunction): DataFrame = {
    df.withColumn("new_col", func(col("col1")))
}

scala REPL非常有助于返回初始化值的类型。

scala> val lkpUDF = udf{(i: Int) => if (i > 0) 1 else 0}
lkpUDF: org.apache.spark.sql.UserDefinedFunction = UserDefinedFunction(<function1>,IntegerType,List(IntegerType))

此外,如果传递给udf包装器的函数的签名包含Any返回类型(如果函数可以返回基元或用户定义的情况,则会出现这种情况)案例类),UDF将无法编译,例如:

java.lang.UnsupportedOperationException: Schema for type Any is not supported