Spark SQL UDF返回带有df.WithColumn()的scala不可变映射
我有案例课Spark SQL UDF返回带有df.WithColumn()的scala不可变映射,scala,apache-spark-sql,user-defined-functions,spark-dataframe,udf,Scala,Apache Spark Sql,User Defined Functions,Spark Dataframe,Udf,我有案例课 case class MyCaseClass(City : String, Extras : Map[String, String]) 以及返回scala.collection.immutable.Map的用户定义函数 def extrasUdf = spark.udf.register( "extras_udf", (age : Int, name : String) => Map("age" -> age.toString, "name" ->
case class MyCaseClass(City : String, Extras : Map[String, String])
以及返回scala.collection.immutable.Map的用户定义函数
def extrasUdf = spark.udf.register(
"extras_udf",
(age : Int, name : String) => Map("age" -> age.toString, "name" -> name)
)
但这种情况例外:
import spark.implicits._
spark.read.options(...).load(...)
.select('City, 'Age, 'Name)
.withColumn("Extras", extrasUdf('Age, 'Name))
.drop('Age)
.drop('Name)
.as[MyCaseClass]
我应该使用spark sql的映射类型(DataTypes.StringType、DataTypes.IntegerType)
但我找不到任何有效的例子
如果我使用scala.collection.Map,这是可行的,但我需要不可变的Map您的代码有很多问题:
- 您使用的是
,它创建了一个注册自定义项的函数,而不是实际创建/注册自定义项。改用def extrastUdf=
val extrasUdf=
- 您在映射中混合了值类型(
和String
),这使得映射成为Int
,因为map[String,Any]
是Any
和String
的常见超类。Spark不支持Int
任何
。您至少可以做两件事:(a)切换到使用字符串映射(使用
,在这种情况下,您不需要UDF,因为您可以简单地使用它)或(b)切换到使用命名结构(同样,不需要UDF)。通常,只有在无法使用现有函数执行所需操作时,才编写UDF。我更喜欢看Hive文档,因为Spark文档非常稀疏age.toString
- 此外,请记住Spark模式中的类型规范(例如,
)与Scala类型(例如,MapType
)完全不同,并且与类型在内部的表示方式以及Scala和Spark数据结构之间的映射方式不同。换句话说,这与可变集合与不可变集合无关Map[\uu,\u]
希望这有帮助 如果没有/使用UDF,是否可以在WithColumn()表达式中放入'Age',仅当名称不为空时才在映射中放入'Age',因为我不希望在映射中有空值?您可以使用
if()
或case当。。。然后
表达式。