[EDIT: Tháng 3 năm 2016: cảm ơn vì đã bỏ phiếu! Mặc dù thực sự, đây không phải là câu trả lời tốt nhất, tôi nghĩ rằng giải pháp dựa trên withColumn
, withColumnRenamed
và cast
đưa ra bởi msemelman, Martin Senne và những người khác đơn giản hơn và sạch hơn].
Tôi nghĩ rằng cách tiếp cận của bạn là ổn, hãy nhớ rằng Spark DataFrame
là một RDD của Hàng (không thay đổi), vì vậy chúng tôi không bao giờ thực sự thay thế một cột, chỉ tạo mới DataFrame
mỗi lần bằng một lược đồ mới.
Giả sử bạn có một df gốc với lược đồ sau:
scala> df.printSchema
root
|-- Year: string (nullable = true)
|-- Month: string (nullable = true)
|-- DayofMonth: string (nullable = true)
|-- DayOfWeek: string (nullable = true)
|-- DepDelay: string (nullable = true)
|-- Distance: string (nullable = true)
|-- CRSDepTime: string (nullable = true)
Và một số UDF được định nghĩa trên một hoặc một số cột:
import org.apache.spark.sql.functions._
val toInt = udf[Int, String]( _.toInt)
val toDouble = udf[Double, String]( _.toDouble)
val toHour = udf((t: String) => "%04d".format(t.toInt).take(2).toInt )
val days_since_nearest_holidays = udf(
(year:String, month:String, dayOfMonth:String) => year.toInt + 27 + month.toInt-12
)
Thay đổi loại cột hoặc thậm chí xây dựng DataFrame mới từ loại khác có thể được viết như sau:
val featureDf = df
.withColumn("departureDelay", toDouble(df("DepDelay")))
.withColumn("departureHour", toHour(df("CRSDepTime")))
.withColumn("dayOfWeek", toInt(df("DayOfWeek")))
.withColumn("dayOfMonth", toInt(df("DayofMonth")))
.withColumn("month", toInt(df("Month")))
.withColumn("distance", toDouble(df("Distance")))
.withColumn("nearestHoliday", days_since_nearest_holidays(
df("Year"), df("Month"), df("DayofMonth"))
)
.select("departureDelay", "departureHour", "dayOfWeek", "dayOfMonth",
"month", "distance", "nearestHoliday")
mang lại:
scala> df.printSchema
root
|-- departureDelay: double (nullable = true)
|-- departureHour: integer (nullable = true)
|-- dayOfWeek: integer (nullable = true)
|-- dayOfMonth: integer (nullable = true)
|-- month: integer (nullable = true)
|-- distance: double (nullable = true)
|-- nearestHoliday: integer (nullable = true)
Điều này là khá gần với giải pháp của riêng bạn. Đơn giản, việc giữ các thay đổi loại và các biến đổi khác dưới dạng riêng biệt udf val
làm cho mã dễ đọc hơn và có thể sử dụng lại.