Переименование названий столбцов в таблице данных СПАРК Скала
Я пытаюсь преобразовать все заголовки / имена столбцов a DataFrame
в Spark-Scala. на данный момент я придумал следующий код, который заменяет только одно имя столбца.
for( i <- 0 to origCols.length - 1) {
df.withColumnRenamed(
df.columns(i),
df.columns(i).toLowerCase
);
}
3 ответа:
если структура плоская:
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)
самое простое, что вы можете сделать, это использовать
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)
если вы хотите переименовать отдельные столбцы, вы можете использовать либо
select
Сalias
:df.select($"_1".alias("x1"))
который можно легко обобщить на несколько столбцов:
val lookup = Map("_1" -> "foo", "_3" -> "bar") df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
или
withColumnRenamed
:df.withColumnRenamed("_1", "x1")
которые используют с
foldLeft
переименовать несколько столбцов:lookup.foldLeft(df)((acc, ca) => acc.withColumnRenamed(ca._1, ca._2))
с вложенными структурами (
structs
) один из возможных вариантов переименования, выбрав всю структуру: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)
обратите внимание, что это может повлиять
nullability
метаданные. Другая возможность состоит в том, чтобы переименовать методом литья: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)
или:
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)
для тех из вас, кто заинтересован в версии PySpark (на самом деле это то же самое в Scala - см. комментарий ниже) :
merchants_df_renamed = merchants_df.toDF( 'merchant_id', 'category', 'subcategory', 'merchant') merchants_df_renamed.printSchema() root |-- merchant_id: integer (nullable = true) |-- category: string (nullable = true) |-- subcategory: string (nullable = true) |-- merchant: string (nullable = true)
def aliasAllColumns(t: DataFrame, p: String = "", s: String = ""): DataFrame = { t.select( t.columns.map { c => t.col(c).as( p + c + s) } : _* ) }
в случае, если это не очевидно, это добавляет префикс и суффикс к каждому из текущих имен столбцов. Это может быть полезно, когда у вас есть две таблицы с одним или несколькими столбцами с тем же именем, и вы хотите присоединиться к ним, но все еще быть в состоянии различать столбцов в результирующей таблице. Было бы неплохо, если бы был аналогичный способ сделать это в "нормальном" SQL.