[편집 : 2016 년 3 월 : 투표 해 주셔서 감사합니다! 정말로,이 내가 기반 솔루션을 생각, 최선의 답변을하지 않습니다 withColumn
, withColumnRenamed
그리고 cast
msemelman에 의해 제시, 마틴 Senne 및 기타] 간단하고 깨끗합니다.
나는 당신의 접근법이 괜찮다고 생각합니다 .Spark DataFrame
는 (불변의) 행의 RDD라는 것을 기억하십시오 . 그래서 우리는 열을 실제로 대체 하지 않으며 DataFrame
매번 새로운 스키마로 새로운 것을 생성 합니다.
다음 스키마가 포함 된 원본 df가 있다고 가정합니다.
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)
그리고 일부 UDF는 하나 이상의 열에 정의되어 있습니다.
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
)
열 유형을 변경하거나 다른 데이터 프레임에서 새 DataFrame을 작성하면 다음과 같이 작성할 수 있습니다.
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")
결과는 다음과 같습니다.
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)
이것은 자신의 솔루션에 매우 가깝습니다. 간단히, 유형 변경 및 기타 변환을 개별적으로 udf val
유지하면 코드를 더 읽기 쉽고 재사용 할 수 있습니다.