Anwenden von IndexToString auf den Feature-Vektor in Spark

Kontext Ich habe einen Datenrahmen, in dem alle kategorialen Werte mit StringIndexer indiziert wurden.

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") 
}

Dann habe ich VectorAssembler verwendet, um alle Merkmalsspalten (einschließlich der indizierten kategorialen) zu vektorisieren.

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

Nach dem Anwenden des Klassifikators und einiger zusätzlicher Schritte erhalte ich einen Datenrahmen mit Beschriftung, Merkmalen und Vorhersage. Ich möchte meinen Merkmalsvektor auf separate Spalten erweitern, um die indizierten Werte wieder in ihre ursprüngliche Zeichenfolgenform zu konvertieren.

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

Frage Gibt es eineinfac oder ist der beste Ansatz, um die Vorhersagespalte irgendwie an den Testdatenrahmen anzuhängen?

Was ich versucht habe:

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

enn ich das anwende, bekomme ich die gewünschten Spalten, aber sie sind in Vektorform (wie beabsichtigt) und geben nicht Double ei

Bearbeiten Die gewünschte Ausgabe ist der ursprüngliche Datenrahmen (d. H. Kategoriale Funktion, res als Zeichenfolge, nicht Index) mit einer zusätzlichen Spalte, die die vorhergesagte Bezeichnung angibt (in meinem Fall 0 oder 1).

Angenommen, die Ausgabe meines Klassifikators sah ungefähr so aus:

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

Durch Anwenden von VectorSlicer auf jedes Feature würde ich erhalten:

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

Was ist toll, aber ich brauche:

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

ie können dann IndexToString verwenden und in Folgendes konvertieren:

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

oder auch

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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage