У меня есть фрейм данных следующей структуры:
A: Array[String] | B: Array[String] | [ ... multiple other columns ...]
=========================================================================
[A, B, C, D] | [1, 2, 3, 4] | [ ... array with 4 elements ... ]
[E, F, G, H, I] | [5, 6, 7, 8, 9] | [ ... array with 5 elements ... ]
[J] | [10] | [ ... array with 1 element ... ]
Я хочу написать UDF, который
- Уплотняет элементы в i-й позиции каждого столбца вDF
- взрывает DF на каждом из этих сжатых кортежей
Получившийся столбец должен выглядеть следующим образом:
ZippedAndExploded: Array[String]
=================================
[A, 1, ...]
[B, 2, ...]
[C, 3, ...]
[D, 4, ...]
[E, 5, ...]
[F, 6, ...]
[G, 7, ...]
[H, 8, ...]
[I, 9, ...]
[J, 10, ...]
В данный момент я используюмножественный вызов (по одному на имя столбца, список имен столбцов собирается во время выполнения) в UDF, например:
val myudf6 = udf((xa:Seq[Seq[String]],xb:Seq[String]) => {
xa.indices.map(i => {
xa(i) :+ xb(i) // Add one element to the zip column
})
})
val allColumnNames = df.columns.filter(...)
for (columnName <- allColumnNames) {
df = df.withColumn("zipped", myudf8(df("zipped"), df(columnName))
}
df = df.explode("zipped")
Поскольку в кадре данных могут быть сотни столбцов, этот итеративный вызов withColumn
кажется, занимает много времени.
Вопрос (ы): возможно ли это сделать с одним UDF и одним DF.withColumn(...)
вызовом?
Важно : UDF долженzip динамическое число столбцов (читается во время выполнения).