Добавление двух столбцов в существующий DataFrame, используя withColumn

У меня есть DataFrame с few columns. Теперь я хочу добавить еще два столбца в существующий DataFrame.

В настоящее время я делаю это с помощью withColumn метода в DataFrame.

например:

df.withColumn("newColumn1", udf(col("somecolumn")))
  .withColumn("newColumn2", udf(col("somecolumn")))

На самом деле я могу вернуть оба новых значения COlumn в один метод UDF с помощью Array [String]. Но в данный момент это то, как я это делаю.

В любом случае, я могу сделать это эффективно? использование explode - хороший вариант здесь?

Даже если я должен использовать explode, я должен использовать withColumn один раз, а затем возвращает значение столбца как Array[String], затем с помощью explode, создать еще два столбца.

Какой из них эффективен? или есть альтернативы?

Ответ 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")