স্পার্ক স্কালায় একটি ডেটা ফ্রেমের কলামের নাম পুনরায় নামকরণ


94

আমি DataFrameস্পার্ক-স্কালায় একটির সমস্ত শিরোনাম / কলামের নাম রূপান্তর করার চেষ্টা করছি । এখন পর্যন্ত আমি নিম্নলিখিত কোড নিয়ে এসেছি যা কেবলমাত্র একটি একক কলামের নাম প্রতিস্থাপন করে।

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

উত্তর:


240

কাঠামো সমতল হলে:

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)

হাই @ শূন্য ৩৩৩ কলামমেনামের সাথে ব্যবহার করার সময় আমি বিশ্লেষণ পেয়ে যাচ্ছি 'সিসি 8 সমাধান করতে পারে না can't 1 'প্রদত্ত ইনপুট কলাম ... এটি CC8.1 ডেটা ফ্রেমে উপলব্ধ থাকলেও ব্যর্থ হয় দয়া করে গাইড করুন।
unk1102

@ u449355 এটি নেস্টেড কলাম বা বিন্দু সম্বলিত কোনটি যদি আমার পক্ষে পরিষ্কার হয় না। পরবর্তী ক্ষেত্রে ব্যাকটিকগুলি কাজ করা উচিত (কমপক্ষে কিছু প্রাথমিক ক্ষেত্রে)।
শূন্য323

4
এর : _*)অর্থ কীdf.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*)
অ্যান্টন কিম

4
আন্তন কিমের প্রশ্নের উত্তর দিতে: এটি : _*হল স্কেল তথাকথিত "স্প্ল্যাট" অপারেটর। এটি মূলত একটি বিন্যাসবিহীন তালিকায় একটি অ্যারের মতো জিনিসটি বিস্ফোরিত করে, যা আপনি যখন অ্যারেটিকে একটি ক্রিয়াকলাপের জন্য নির্ধারণ করতে চান যা কার্যকর হয় তবে এটির একটি সংস্করণ থাকে না List[]। আপনি যদি পার্লের সাথে কিছুটা পরিচিত হন তবে এটি some_function(@my_array) # "splatted"এবং এর মধ্যে পার্থক্য some_function(\@my_array) # not splatted ... in perl the backslash "\" operator returns a reference to a thing
মাইলো স্টোন

4
এই বিবৃতিটি আমার কাছে সত্যিই অস্পষ্ট df.select(df.columns.map(c => col(c).as(lookup.getOrElse(c, c))): _*).. আপনি দয়া করে এটি পচিয়ে দিতে পারবেন? বিশেষত lookup.getOrElse(c,c)অংশ।
Aetos

19

পিআইস্পার্ক সংস্করণে আপনার আগ্রহী তাদের জন্য (আসলে এটি স্কালায় সমান - নীচে মন্তব্য দেখুন):

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

    merchants_df_renamed.printSchema()

ফলাফল:

রুট
| - merchant_id: পূর্ণসংখ্যা (nullable = সত্য)
| - বিভাগ: STRING (nullable = সত্য)
| - উপবিষয়শ্রেণীটি: STRING (nullable = সত্য)
| - বণিক: STRING (nullable = সত্য)


4
ব্যবহার করে toDF()DataFrame কলাম পুনঃনামকরনের সতর্কতা অবলম্বন করা আবশ্যক হবে। ' এই পদ্ধতিটি অন্যদের তুলনায় অনেক ধীর গতিতে কাজ করে। আমার কাছে ডেটাফ্রেমে 100 এম রেকর্ড রয়েছে এবং এটিতে সহজ গণনা কোয়েরি রয়েছে এটিতে ~ 3s লাগে, তবে toDF()পদ্ধতি সহ একই ক্যোয়ারিতে ~ 16s লাগে। তবে select col AS col_newনাম পরিবর্তনের জন্য যখন ব্যবহারের পদ্ধতিটি পাই তখন আমি আবার ~ 3s পাই। আরও পাঁচগুণ দ্রুত! ২.৩.২.৩ স্পার্ক করুন
ইহোর কোনোভালেনকো

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

যদি বিষয়টি সুস্পষ্ট না হয় তবে এটি বর্তমান কলামের প্রত্যেকটির নামের সাথে একটি উপসর্গ এবং প্রত্যয় যুক্ত করে। এটি কার্যকর হতে পারে যখন আপনার এক বা একাধিক কলামের একই নামযুক্ত দুটি টেবিল থাকে এবং আপনি সেগুলিতে যোগ দিতে চান তবে ফলস্বরূপ সারণিতে কলামগুলি ছিন্ন করতে সক্ষম হবেন। "নরমাল" এসকিউএল-তে এটি করার মতো কোনও উপায় থাকলে এটি অবশ্যই দুর্দান্ত।


এটি অবশ্যই নিশ্চিত করুন, সুন্দর এবং মার্জিত
thebluephantom

1

ধরা যাক ডেটাফ্রেম ডিএফের 3 টি কলাম আইডি 1, নাম 1, মূল্য 1 রয়েছে এবং আপনি তাদের নামটি আইডি 2, নাম 2, মূল্য 2 এ রাখতে চান

val list = List("id2", "name2", "price2")
import spark.implicits._
val df2 = df.toDF(list:_*)
df2.columns.foreach(println)

আমি এই পদ্ধতিকে অনেক ক্ষেত্রে দরকারী বলে মনে করেছি।


0

টো টেবিল জয়েন যুক্ত কীটির নাম পরিবর্তন করে না

// 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)
}

কাজ!


0
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: _*)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.