¿Cómo convertir una columna que se ha leído como una cadena en una columna de matrices? es decir, convertir desde el siguiente esquema

scala> test.printSchema
root
 |-- a: long (nullable = true)
 |-- b: string (nullable = true)

+---+---+
|  a|  b|
+---+---+
|  1|2,3|
+---+---+
|  2|4,5|
+---+---+

Para:

scala> test1.printSchema
root
 |-- a: long (nullable = true)
 |-- b: array (nullable = true)
 |    |-- element: long (containsNull = true)

+---+-----+
|  a|  b  |
+---+-----+
|  1|[2,3]|
+---+-----+
|  2|[4,5]|
+---+-----+

Comparta la implementación de scala y python si es posible. En una nota relacionada, ¿cómo lo cuido mientras leo del archivo? Tengo datos con ~ 450 columnas y pocas de ellas quiero especificar en este formato. Actualmente estoy leyendo en pyspark de la siguiente manera:

df = spark.read.format('com.databricks.spark.csv').options(
    header='true', inferschema='true', delimiter='|').load(input_file)

Gracias.

13
Nikhil Utane 22 jun. 2017 a las 07:31

3 respuestas

La mejor respuesta

Hay varios métodos,

La mejor manera de hacerlo es usar la función split y enviar a array<long>

data.withColumn("b", split(col("b"), ",").cast("array<long>"))

También puede crear udf simple para convertir los valores.

val tolong = udf((value : String) => value.split(",").map(_.toLong))

data.withColumn("newB", tolong(data("b"))).show

¡Espero que esto ayude!

14
thebluephantom 28 jul. 2019 a las 18:03

El uso de un UDF le proporcionaría el esquema exacto requerido. Me gusta esto:

val toArray = udf((b: String) => b.split(",").map(_.toLong))

val test1 = test.withColumn("b", toArray(col("b")))

Te daría el siguiente esquema:

scala> test1.printSchema
root
 |-- a: long (nullable = true)
 |-- b: array (nullable = true)
 |    |-- element: long (containsNull = true)

+---+-----+
|  a|  b  |
+---+-----+
|  1|[2,3]|
+---+-----+
|  2|[4,5]|
+---+-----+

En cuanto a la aplicación del esquema en la lectura del archivo, creo que es una tarea difícil. Entonces, por ahora puede aplicar la transformación después de crear DataFrameReader de test.

¡Espero que esto ayude!

2
himanshuIIITian 22 jun. 2017 a las 04:47

En python (pyspark) sería:

from pyspark.sql.types import *
from pyspark.sql.functions import col, split
test = test.withColumn(
        "b",
        split(col("b"), ",\s*").cast("array<int>").alias("ev")
 )
1
Ariana Bermúdez 24 abr. 2018 a las 16:30