在 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
问题是1
是Int
,而make
是BigInt
,所以udf中的方法返回Any
。 udf 函数不支持Any
,因此您会看到错误。使类型一致使方法返回BigInt
并解决问题。也可以将make
的类型设为Int
【讨论】:
我像你的答案一样更改了代码。然后我得到另一个错误:java.lang.UnsupportedOperationException:不支持 scala.math.BigInt 类型的架构 @RyanWang - 尝试更改为long
?以上是关于在 Spark 中创建 UDF 时出错的主要内容,如果未能解决你的问题,请参考以下文章