Aplicando IndexToString al vector de características en Spark

Contexto: Tengo un marco de datos donde todos los valores categóricos se han indexado usando StringIndexer.

val categoricalColumns = df.schema.collect { case StructField(name, StringType, nullable, meta) => name }    

val categoryIndexers = categoricalColumns.map {
  col => new StringIndexer().setInputCol(col).setOutputCol(s"${col}Indexed") 
}

Luego usé VectorAssembler para vectorizar todas las columnas de características (incluidas las categóricas indexadas).

val assembler = new VectorAssembler()
    .setInputCols(dfIndexed.columns.diff(List("label") ++ categoricalColumns))
    .setOutputCol("features")

Después de aplicar el clasificador y algunos pasos adicionales, termino con un marco de datos que tiene etiqueta, características y predicción. Me gustaría expandir mi vector de características para separar columnas con el fin de convertir los valores indexados a su forma de cadena original.

val categoryConverters = categoricalColumns.zip(categoryIndexers).map {
colAndIndexer => new IndexToString().setInputCol(s"${colAndIndexer._1}Indexed").setOutputCol(colAndIndexer._1).setLabels(colAndIndexer._2.fit(df).labels)
}

Pregunta: Hay unsencillo forma de hacerlo, o es el mejor enfoque para adjuntar de alguna manera la columna de predicción al marco de datos de prueba?

Lo que he intentado:

val featureSlicers = categoricalColumns.map {
  col => new VectorSlicer().setInputCol("features").setOutputCol(s"${col}Indexed").setNames(Array(s"${col}Indexed"))
}

La aplicación de esto me da las columnas que quiero, pero están en forma de Vector (como debe ser) y no escriben Doble.

Editar: El resultado deseado es el marco de datos original (es decir, una característica categórica, res como Cadena no índice) con una columna adicional que indica la etiqueta predicha (que en mi caso es 0 o 1).

Por ejemplo, supongamos que la salida de mi clasificador se parece a esto:

+-----+---------+----------+
|label| features|prediction|
+-----+---------+----------+
|  1.0|[0.0,3.0]|       1.0|
+-----+---------+----------+

Al aplicar VectorSlicer en cada función obtendría:

+-----+---------+----------+-------------+-------------+
|label| features|prediction|statusIndexed|artistIndexed|
+-----+---------+----------+-------------+-------------+
|  1.0|[0.0,3.0]|       1.0|        [0.0]|        [3.0]|
+-----+---------+----------+-------------+-------------+

Lo cual es genial, pero necesito:

+-----+---------+----------+-------------+-------------+
|label| features|prediction|statusIndexed|artistIndexed|
+-----+---------+----------+-------------+-------------+
|  1.0|[0.0,3.0]|       1.0|         0.0 |         3.0 |
+-----+---------+----------+-------------+-------------+

Para luego poder usar IndexToString y convertirlo a:

+-----+---------+----------+-------------+-------------+
|label| features|prediction|    status   |    artist   |
+-----+---------+----------+-------------+-------------+
|  1.0|[0.0,3.0]|       1.0|        good |  Pink Floyd |
+-----+---------+----------+-------------+-------------+

o incluso:

+-----+----------+-------------+-------------+
|label|prediction|    status   |    artist   |
+-----+----------+-------------+-------------+
|  1.0|       1.0|        good |  Pink Floyd |
+-----+----------+-------------+-------------+

Respuestas a la pregunta(1)

Su respuesta a la pregunta