关于scala:Spark UDF作为函数参数,UDF不在函数范围内

Spark UDF as function parameter, UDF is not in function scope

我想将一些UDF作为函数参数与数据帧一起传递。

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

这是示例代码-

1
2
3
4
5
6
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")))

而不是执行上述操作,我理想上想做这样的事情-

1
2
3
4
5
6
7
8
9
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非常简单,但就我而言,它可以返回原始类型或用户定义的案例类类型。任何想法/指针将不胜感激。谢谢。


具有适当签名的功能必须是:

1
2
3
4
5
import org.apache.spark.sql.UserDefinedFunction

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

scala REPL在返回初始化值的类型方面非常有帮助。

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

此外,如果传递给udfpackage器的函数的签名由Any返回类型组成(如果函数可以返回原始或用户定义的case类,则为这种情况), UDF将无法编译,并出现如下异常:

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