2016-02-24 12 views
47

Sto provando a convertire tutte le intestazioni/nomi di colonna di un DataFrame in Spark-scala. come ora mi viene in mente il seguente codice che sostituisce solo un nome di singola colonna. Per favore aiutaci su questo.Rinominare i nomi di colonna di un frame di dati in spark scala

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

risposta

138

Se la struttura è piatta:

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) 

la cosa più semplice che si può fare è quello di utilizzare toDF metodo:

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) 

Se si desidera rinominare le colonne individuali che è possibile utilizzare sia select con alias:

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

facilmente generalizzabile a più colonne:

val lookup = Map("_1" -> "foo", "_3" -> "bar") 

df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*) 

o withColumnRenamed:

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

che utilizzano con foldLeft per rinominare più colonne:

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

Con strutture annidate (structs) una possibile opzione è la ridenominazione selezionando un intero str ucture:

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) 

Si noti che può influenzare nullability metadati. Un'altra possibilità è quella di rinominare dal 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) 
+0

Hi @ zero323 Quando si utilizza withColumnRenamed Sono ottenere AnalysisException non può risolvere 'CC8. 1 'dato colonne di input ... Fallisce anche se CC8.1 è disponibile in DataFrame per favore guida. – u449355

+0

@ u449355 Non è chiaro per me se questa è una colonna nidificata o una che contiene punti. Nel caso successivo i backtick dovrebbero funzionare (almeno in alcuni casi di base). – zero323

+0

cosa significa ': _ *)' significa in 'df.select (df.columns.map (c => col (c) .as (lookup.getOrElse (c, c))): _ *)' –

5

Per coloro che sono interessati nella versione PySpark:

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) 
2
def aliasAllColumns(t: DataFrame, p: String = "", s: String = ""): DataFrame = 
{ 
    t.select(t.columns.map { c => t.col(c).as(p + c + s) } : _*) 
}