Luego de mirar en diversos repositorios y foros de internet al concluir nos encontramos con la solución que te compartiremos aquí.
Solución:
wow, a mi compañero de trabajo se le ocurrió una solución extremadamente elegante:
scala> recs.select($"userId", $"recommendations.itemId").show
+------+------+
|userId|itemId|
+------+------+
| 1|[1, 2]|
| 2|[0, 4]|
+------+------+
Entonces, tal vez la API de Spark ML no sea tan difícil después de todo 🙂
Con un array como el tipo de una columna, por ejemplo recommendations
sería bastante productivo usando la función de explosión (o el operador flatMap más avanzado).
explotar(e: Columna): Columna Crea una nueva fila para cada elemento en el dado array o columna de mapa.
Eso le da estructuras desnudas para trabajar.
import org.apache.spark.sql.types._
val structType = new StructType().
add($"itemId".int).
add($"rating".float)
val arrayType = ArrayType(structType)
val recs = Seq((1, Array((1, .7), (2, .5))), (2, Array((0, .9), (4, .1)))).
toDF("userId", "recommendations").
select($"userId", $"recommendations" cast arrayType)
val exploded = recs.withColumn("recs", explode($"recommendations"))
scala> exploded.show
+------+------------------+-------+
|userId| recommendations| recs|
+------+------------------+-------+
| 1|[[1,0.7], [2,0.5]]|[1,0.7]|
| 1|[[1,0.7], [2,0.5]]|[2,0.5]|
| 2|[[0,0.9], [4,0.1]]|[0,0.9]|
| 2|[[0,0.9], [4,0.1]]|[4,0.1]|
+------+------------------+-------+
las estructuras son agradables en select
operador con *
(estrella) para aplanarlos en columnas según los campos de estructura.
Podrías hacerlo select($"element.*")
.
scala> exploded.select("userId", "recs.*").show
+------+------+------+
|userId|itemId|rating|
+------+------+------+
| 1| 1| 0.7|
| 1| 2| 0.5|
| 2| 0| 0.9|
| 2| 4| 0.1|
+------+------+------+
Creo que eso podría hacer lo que buscas.
ps Manténgase alejado de los UDF el mayor tiempo posible, ya que “activan” la conversión de filas desde el formato interno (InternalRow
) a objetos JVM que pueden generar un exceso de GC.
Valoraciones y reseñas
Si para ti ha sido de provecho este artículo, sería de mucha ayuda si lo compartes con más seniors así contrubuyes a extender este contenido.