tutorial spark read functions example español create scala apache-spark dataframe apache-spark-sql

read - Renombrar nombres de columna de un DataFrame en Spark Scala



spark sql functions (3)

Estoy tratando de convertir todos los encabezados / nombres de columna de un DataFrame en Spark-Scala. a partir de ahora se me ocurre el siguiente código que solo reemplaza el nombre de una sola columna.

for( i <- 0 to origCols.length - 1) { df.withColumnRenamed( df.columns(i), df.columns(i).toLowerCase ); }


Para aquellos de ustedes interesados ​​en la versión de PySpark (en realidad es lo mismo en Scala, vea el comentario a continuación):

merchants_df_renamed = merchants_df.toDF( ''merchant_id'', ''category'', ''subcategory'', ''merchant'') merchants_df_renamed.printSchema()

Resultado:

raíz
| - merchant_id: integer (nullable = true)
| - categoría: cadena (anulable = verdadero)
| - subcategoría: cadena (anulable = verdadero)
| - comerciante: cadena (anulable = verdadero)


Si la estructura es plana:

val df = Seq((1L, "a", "foo", 3.0)).toDF df.printSchema // root // |-- _1: long (nullable = false) // |-- _2: string (nullable = true) // |-- _3: string (nullable = true) // |-- _4: double (nullable = false)

Lo más simple que puede hacer es utilizar el método toDF :

val newNames = Seq("id", "x1", "x2", "x3") val dfRenamed = df.toDF(newNames: _*) dfRenamed.printSchema // root // |-- id: long (nullable = false) // |-- x1: string (nullable = true) // |-- x2: string (nullable = true) // |-- x3: double (nullable = false)

Si desea cambiar el nombre de las columnas individuales, puede usar select con alias :

df.select($"_1".alias("x1"))

que se puede generalizar fácilmente a múltiples columnas:

val lookup = Map("_1" -> "foo", "_3" -> "bar") df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)

o con withColumnRenamed :

df.withColumnRenamed("_1", "x1")

que se usan con foldLeft para cambiar el nombre de varias columnas:

lookup.foldLeft(df)((acc, ca) => acc.withColumnRenamed(ca._1, ca._2))

Con estructuras anidadas ( structs ), una opción posible es renombrar seleccionando una estructura completa:

val nested = spark.read.json(sc.parallelize(Seq( """{"foobar": {"foo": {"bar": {"first": 1.0, "second": 2.0}}}, "id": 1}""" ))) nested.printSchema // root // |-- foobar: struct (nullable = true) // | |-- foo: struct (nullable = true) // | | |-- bar: struct (nullable = true) // | | | |-- first: double (nullable = true) // | | | |-- second: double (nullable = true) // |-- id: long (nullable = true) @transient val foobarRenamed = struct( struct( struct( $"foobar.foo.bar.first".as("x"), $"foobar.foo.bar.first".as("y") ).alias("point") ).alias("location") ).alias("record") nested.select(foobarRenamed, $"id").printSchema // root // |-- record: struct (nullable = false) // | |-- location: struct (nullable = false) // | | |-- point: struct (nullable = false) // | | | |-- x: double (nullable = true) // | | | |-- y: double (nullable = true) // |-- id: long (nullable = true)

Tenga en cuenta que puede afectar los metadatos de nullability . Otra posibilidad es cambiar el nombre mediante el casting:

nested.select($"foobar".cast( "struct<location:struct<point:struct<x:double,y:double>>>" ).alias("record")).printSchema // root // |-- record: struct (nullable = true) // | |-- location: struct (nullable = true) // | | |-- point: struct (nullable = true) // | | | |-- x: double (nullable = true) // | | | |-- y: double (nullable = true)

o:

import org.apache.spark.sql.types._ nested.select($"foobar".cast( StructType(Seq( StructField("location", StructType(Seq( StructField("point", StructType(Seq( StructField("x", DoubleType), StructField("y", DoubleType))))))))) ).alias("record")).printSchema // root // |-- record: struct (nullable = true) // | |-- location: struct (nullable = true) // | | |-- point: struct (nullable = true) // | | | |-- x: double (nullable = true) // | | | |-- y: double (nullable = true)


def aliasAllColumns(t: DataFrame, p: String = "", s: String = ""): DataFrame = { t.select( t.columns.map { c => t.col(c).as( p + c + s) } : _* ) }

En caso de que no sea obvio, esto agrega un prefijo y un sufijo a cada uno de los nombres de columna actuales. Esto puede ser útil cuando tiene dos tablas con una o más columnas que tienen el mismo nombre, y desea unirlas, pero aún así puede desambiguar las columnas en la tabla resultante. Seguro que sería bueno si hubiera una forma similar de hacer esto en SQL "normal".