¿Cómo vectorizar columnas de DataFrame para algoritmos de ML?

tener un DataFrame con algunos valores de cadena categóricos (por ejemplo, uuid | url | browser).

Me gustaría convertirlo en un doble para ejecutar un algoritmo ML que acepte doble matriz.

Como método de conversión utilicé StringIndexer (chispa 1.4) que correlaciona mis valores de cadena con valores dobles, así que definí una función como esta:

def str(arg: String, df:DataFrame) : DataFrame = ( val indexer = new StringIndexer().setInputCol(arg).setOutputCol(arg+"_index") val newDF = indexer.fit(df).transform(df) return newDF ) 

Ahora el problema es que iteraría la columna foreach de un df, llamaría a esta función y agregaría (o convertiría) la columna de cadena original en la columna doble analizada, por lo que el resultado sería:

Df inicial:

 [String: uuid|String: url| String: browser] 

Df final:

 [String: uuid|Double: uuid_index|String: url|Double: url_index|String: browser|Double: Browser_index] 

Gracias por adelantado

Simplemente puede foldLeft hacia la foldLeft sobre la Array de columnas:

 val transformed: DataFrame = df.columns.foldLeft(df)((df, arg) => str(arg, df)) 

Aún así, argumentaré que no es un buen enfoque. Como src descarta StringIndexerModel , no se puede usar cuando se obtienen datos nuevos. Por eso, recomendaría usar Pipeline :

 import org.apache.spark.ml.Pipeline val transformers: Array[org.apache.spark.ml.PipelineStage] = df.columns.map( cname => new StringIndexer() .setInputCol(cname) .setOutputCol(s"${cname}_index") ) // Add the rest of your pipeline like VectorAssembler and algorithm val stages: Array[org.apache.spark.ml.PipelineStage] = transformers ++ ??? val pipeline = new Pipeline().setStages(stages) val model = pipeline.fit(df) model.transform(df) 

VectorAssembler se puede incluir así:

 val assembler = new VectorAssembler() .setInputCols(df.columns.map(cname => s"${cname}_index")) .setOutputCol("features") val stages = transformers :+ assembler 

También podría usar RFormula , que es menos personalizable, pero mucho más conciso:

 import org.apache.spark.ml.feature.RFormula val rf = new RFormula().setFormula(" ~ uuid + url + browser - 1") val rfModel = rf.fit(dataset) rfModel.transform(dataset)