Saltar al contenido

Cómo aplanar columnas de tipo array de estructuras (según lo devuelto por Spark ML API)?

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 recommendationsserí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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *