Si la estructura es plana:
val df = Seq((1L, "a", "foo", 3.0)).toDF
df.printSchema
lo más simple que puedes hacer es usar el toDF
método:
val newNames = Seq("id", "x1", "x2", "x3")
val dfRenamed = df.toDF(newNames: _*)
dfRenamed.printSchema
Si desea cambiar el nombre de columnas individuales, puede usar select
con alias
:
df.select($"_1".alias("x1"))
que se puede generalizar fácilmente a varias columnas:
val lookup = Map("_1" -> "foo", "_3" -> "bar")
df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
o bien withColumnRenamed
:
df.withColumnRenamed("_1", "x1")
que 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 cambiar el nombre 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
@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
Tenga en cuenta que puede afectar a los nullability
metadatos. Otra posibilidad es cambiar el nombre lanzando:
nested.select($"foobar".cast(
"struct<location:struct<point:struct<x:double,y:double>>>"
).alias("record")).printSchema
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
: _*)
significa endf.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
: _*
es el llamado operador "splat" de scala. Básicamente, descompone una cosa similar a una matriz en una lista no contenida, lo cual es útil cuando desea pasar la matriz a una función que toma un número arbitrario de argumentos, pero no tiene una versión que toma unList[]
. Si está familiarizado con Perl, es la diferencia entresome_function(@my_array) # "splatted"
ysome_function(\@my_array) # not splatted ... in perl the backslash "\" operator returns a reference to a thing
.df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
. ¿Podría descomponerla por favor? especialmente lalookup.getOrElse(c,c)
parte.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:
fuente
toDF()
para cambiar el nombre de las columnas en DataFrame debe tener cuidado. Este método funciona mucho más lento que otros. Tengo un DataFrame que contiene 100 millones de registros y una consulta de recuento simple toma ~ 3 s, mientras que la misma consulta con eltoDF()
método toma ~ 16 s. Pero cuando uso elselect col AS col_new
método para cambiar el nombre, obtengo ~ 3s nuevamente. ¡Más de 5 veces más rápido! Spark 2.3.2.3def 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 puede eliminar la ambigüedad de las columnas en la tabla resultante. Seguro que sería bueno si hubiera una forma similar de hacer esto en SQL "normal".
fuente
Suponga que el marco de datos df tiene 3 columnas id1, name1, price1 y desea cambiarles el nombre a id2, name2, price2
val list = List("id2", "name2", "price2") import spark.implicits._ val df2 = df.toDF(list:_*) df2.columns.foreach(println)
Encontré este enfoque útil en muchos casos.
fuente
unirse a la mesa de remolque no cambiar el nombre de la clave unida
// method 1: create a new DF day1 = day1.toDF(day1.columns.map(x => if (x.equals(key)) x else s"${x}_d1"): _*) // method 2: use withColumnRenamed for ((x, y) <- day1.columns.filter(!_.equals(key)).map(x => (x, s"${x}_d1"))) { day1 = day1.withColumnRenamed(x, y) }
¡trabajos!
fuente
Sometime we have the column name is below format in SQLServer or MySQL table Ex : Account Number,customer number But Hive tables do not support column name containing spaces, so please use below solution to rename your old column names. Solution: val renamedColumns = df.columns.map(c => df(c).as(c.replaceAll(" ", "_").toLowerCase())) df = df.select(renamedColumns: _*)
fuente