Jika strukturnya datar:
val df = Seq((1L, "a", "foo", 3.0)).toDF
df.printSchema
hal paling sederhana yang dapat Anda lakukan adalah menggunakan toDF
metode:
val newNames = Seq("id", "x1", "x2", "x3")
val dfRenamed = df.toDF(newNames: _*)
dfRenamed.printSchema
Jika Anda ingin mengganti nama kolom individu, Anda dapat menggunakan select
dengan alias
:
df.select($"_1".alias("x1"))
yang dapat dengan mudah digeneralisasikan ke beberapa kolom:
val lookup = Map("_1" -> "foo", "_3" -> "bar")
df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
atau withColumnRenamed
:
df.withColumnRenamed("_1", "x1")
yang digunakan dengan foldLeft
untuk mengganti nama beberapa kolom:
lookup.foldLeft(df)((acc, ca) => acc.withColumnRenamed(ca._1, ca._2))
Dengan struktur bersarang ( structs
), satu opsi yang memungkinkan adalah mengganti nama dengan memilih seluruh struktur:
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
Perhatikan bahwa ini dapat memengaruhi nullability
metadata. Kemungkinan lain adalah mengganti nama dengan casting:
nested.select($"foobar".cast(
"struct<location:struct<point:struct<x:double,y:double>>>"
).alias("record")).printSchema
atau:
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
: _*)
artinya didf.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
: _*
adalah scala yang disebut operator "percikan". Ini pada dasarnya meledakkan hal yang mirip larik ke dalam daftar yang tidak terkendali, yang berguna saat Anda ingin meneruskan larik ke fungsi yang menggunakan sejumlah argumen, tetapi tidak memiliki versi yang membutuhkanList[]
. Jika Anda sama sekali tidak asing dengan Perl, itulah perbedaan antarasome_function(@my_array) # "splatted"
dansome_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))): _*)
.. Bisakah Anda menguraikannya? terutamalookup.getOrElse(c,c)
bagiannya.Bagi Anda yang tertarik dengan versi PySpark (sebenarnya sama di Scala - lihat komentar di bawah):
merchants_df_renamed = merchants_df.toDF( 'merchant_id', 'category', 'subcategory', 'merchant') merchants_df_renamed.printSchema()
Hasil:
sumber
toDF()
untuk mengganti nama kolom di DataFrame harus berhati-hati. Metode ini bekerja lebih lambat dari yang lain. Saya memiliki DataFrame berisi 100 juta catatan dan permintaan hitungan sederhana di atasnya mengambil ~ 3s, sedangkan permintaan yang sama dengantoDF()
metode take ~ 16s. Tetapi ketika menggunakanselect col AS col_new
metode untuk mengganti nama saya mendapatkan ~ 3s lagi. Lebih dari 5 kali lebih cepat! 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) } : _* ) }
Jika tidak jelas, ini menambahkan prefiks dan sufiks ke setiap nama kolom saat ini. Ini dapat berguna ketika Anda memiliki dua tabel dengan satu atau lebih kolom memiliki nama yang sama, dan Anda ingin menggabungkannya tetapi masih dapat menghilangkan ambiguitas kolom dalam tabel resultan. Pasti akan menyenangkan jika ada cara serupa untuk melakukan ini dalam SQL "normal".
sumber
Misalkan df dataframe memiliki 3 kolom id1, name1, price1 dan Anda ingin mengganti namanya menjadi id2, name2, price2
val list = List("id2", "name2", "price2") import spark.implicits._ val df2 = df.toDF(list:_*) df2.columns.foreach(println)
Saya menemukan pendekatan ini berguna dalam banyak kasus.
sumber
tow table join tidak mengubah nama kunci yang digabungkan
// 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) }
berhasil!
sumber
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: _*)
sumber