Ответ 1
AFAIk вам нужно позвонить с помощью withColumn
дважды (один раз для каждого нового столбца). Но если ваш UDF вычислительно дорого, вы можете избежать назвать дважды хранение "сложным" результата во временной колонке, а затем "распаковывать" результат, например, с помощью apply
метода столбца (который дает доступ к элементу массива):
val myUDf = udf((s:String) => Array(s.toUpperCase(),s.toLowerCase()))
val df = sc.parallelize(Seq("Peter","John")).toDF("name")
val newDf = df
.withColumn("udfResult",myUDf(col("name")))
.withColumn("uppercaseColumn", col("udfResult")(0))
.withColumn("lowercaseColumn", col("udfResult")(1))
.drop("udfResult")
newDf.show()
дает
+-----+---------------+---------------+
| name|uppercaseColumn|lowercaseColumn|
+-----+---------------+---------------+
|Peter| PETER| peter|
| John| JOHN| john|
+-----+---------------+---------------+
Я делаю это довольно часто, но не использую массивы, но используя классы case или кортежи в результате udf
РЕДАКТИРОВАТЬ:
Когда UDF вернет кортеж, распаковка будет выглядеть так:
val newDf = df
.withColumn("udfResult",myUDf(col("name")))
.withColumn("lowercaseColumn", col("udfResult._1"))
.withColumn("uppercaseColumn", col("udfResult._2"))
.drop("udfResult")