在 Spark 中创建 UDF 时出错

Posted

技术标签:

【中文标题】在 Spark 中创建 UDF 时出错【英文标题】:Error while creating a UDF in Spark 【发布时间】:2018-01-16 06:58:01 【问题描述】:

我正在尝试使用以下代码在 Spark 中创建 UDF

val makeSIfTesla = udf (make: BigInt) => if(make == 0) 1 else make

但我收到以下错误:

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

为什么?

【问题讨论】:

1 是整数,make 是 BigInt。让它们都一样。 【参考方案1】:

您收到错误是因为您将 1 作为整数返回。此外,hive 中的bigint 实际上是Long。所以你的else 正在返回Long,而你的if 正在返回一个Int,这使得你的UDF Any 的返回类型不受Spark DataFrame 的支持。 Here's a list of supported datatypes

如果你使用df.schema,它会告诉你你真正需要的是LongType

val df = sqlContext.sql(" select cast(2 as bigint) as a ")
// df: org.apache.spark.sql.DataFrame = [a: bigint]

df.printSchema
// root
//  |-- a: long (nullable = false)


df.schema
// res16: org.apache.spark.sql.types.StructType = StructType(StructField(a,LongType,false))

您的 UDF 应该类似于:

val makeSIfTesla = udf (make: Long) => if(make == 0) 1.toLong else make
//makeSIfTesla : UserDefinedFunction = UserDefinedFunction(<function1>,LongType,List(LongType))

但是,对于这样简单的事情,您真的不需要 UDF。您可以使用 Spark 中提供的 when-otherwise 构造。

df.withColumn("x" , when($"x" === lit(0) , lit(1) ).otherwise($"x") )

x 是您传递给 UDF makeSIfTesla 的列。

【讨论】:

【参考方案2】:

修复如下代码:

val makeSIfTesla = udf (make: BigInt) => if(make == 0) BigInt(1) else make

问题是1Int,而makeBigInt,所以udf中的方法返回Any。 udf 函数不支持Any,因此您会看到错误。使类型一致使方法返回BigInt 并解决问题。也可以将make的类型设为Int

【讨论】:

我像你的答案一样更改了代码。然后我得到另一个错误:java.lang.UnsupportedOperationException:不支持 scala.math.BigInt 类型的架构 @RyanWang - 尝试更改为 long?

以上是关于在 Spark 中创建 UDF 时出错的主要内容,如果未能解决你的问题,请参考以下文章

Hive UDF 运行:在 hive 中创建临时函数时出错

在 SQL Server 2005 中创建 UDF 时出错

火花在UDF中创建数据框

关于在 Spark Scala 中创建用户定义函数 (UDF)

如何在 Spark 中创建 UDF 以支持自定义谓词

在 Spark 中创建数据帧时出错