Kontekst: Mam ramkę danych, w której wszystkie wartości kategoryczne zostały zindeksowane przy użyciu StringIndexer.Stosowanie indeksu IndexToString do wektora funkcji w Spark
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")
}
Następnie użyłem VectorAssembler do wektoryzacji wszystkich kolumn elementów (w tym indeksowanych kategorii).
val assembler = new VectorAssembler()
.setInputCols(dfIndexed.columns.diff(List("label") ++ categoricalColumns))
.setOutputCol("features")
Po zastosowaniu klasyfikatora i kilku dodatkowych czynności uzyskuję ramkę danych z etykietą, funkcjami i podpowiedziami. Chciałbym rozwinąć mój wektor funkcji, aby oddzielić kolumny, aby przekonwertować indeksowane wartości z powrotem na ich pierwotną formę String.
val categoryConverters = categoricalColumns.zip(categoryIndexers).map {
colAndIndexer => new IndexToString().setInputCol(s"${colAndIndexer._1}Indexed").setOutputCol(colAndIndexer._1).setLabels(colAndIndexer._2.fit(df).labels)
}
Pytanie: Czy istnieje prosty sposobem osiągnięcia tego, czy jest to najlepsze podejście do jakoś podłączyć kolumny do predykcji ramki danych testowej?
Co próbowałem:
val featureSlicers = categoricalColumns.map {
col => new VectorSlicer().setInputCol("features").setOutputCol(s"${col}Indexed").setNames(Array(s"${col}Indexed"))
}
Stosując ten daje mi kolumny, które chcę, ale są one w postaci wektorowej (jak to ma zrobić), a nie typu double.
Edycja: żądana jest oryginalny ramki danych (tj kategoryczne cechy jak STRING indeksu) z dodatkową kolumną co wskazuje przewidywany etykietę (moim przypadku jest 0 lub 1).
Na przykład, powiedzmy wyjście mojego klasyfikatora wyglądał mniej więcej tak:
+-----+---------+----------+
|label| features|prediction|
+-----+---------+----------+
| 1.0|[0.0,3.0]| 1.0|
+-----+---------+----------+
Stosując VectorSlicer na każdej funkcji chciałbym uzyskać:
+-----+---------+----------+-------------+-------------+
|label| features|prediction|statusIndexed|artistIndexed|
+-----+---------+----------+-------------+-------------+
| 1.0|[0.0,3.0]| 1.0| [0.0]| [3.0]|
+-----+---------+----------+-------------+-------------+
co jest dobre, ale muszę:
+-----+---------+----------+-------------+-------------+
|label| features|prediction|statusIndexed|artistIndexed|
+-----+---------+----------+-------------+-------------+
| 1.0|[0.0,3.0]| 1.0| 0.0 | 3.0 |
+-----+---------+----------+-------------+-------------+
aby następnie móc korzystać IndexToString i przekonwertować go do:
+-----+---------+----------+-------------+-------------+
|label| features|prediction| status | artist |
+-----+---------+----------+-------------+-------------+
| 1.0|[0.0,3.0]| 1.0| good | Pink Floyd |
+-----+---------+----------+-------------+-------------+
lub nawet:
+-----+----------+-------------+-------------+
|label|prediction| status | artist |
+-----+----------+-------------+-------------+
| 1.0| 1.0| good | Pink Floyd |
+-----+----------+-------------+-------------+
Mam podobny problem. Mam zestaw danych tysięcy lub kolumn i niektóre z nich są kategoryczne, więc muszę "podzielić" je na więcej kolumn za pomocą 'StringIndexer' i' OneHotEncoder'. Problem pojawia się, gdy próbuję zrozumieć, co reprezentuje każdą cechę połączonego wektora. –
Czy istnieje jakiś powód, dla którego należy najpierw usunąć dane wejściowe? – zero323
Tak. Klasyfikacja algo oczekuje ramki danych z kolumną "etykieta" i "funkcja". Tam, gdzie kolumna funkcji jest wektorem, nie można mieć łańcuchów. Aby było jasne, nadal mam oryginalną ramkę danych ze wszystkimi danymi wejściowymi. – gstvolvr