2016-10-25 15 views
2

我想使用Spark和Scala來投射數據框的模式以更改某些列的類型 。Spark和Scala中的數據框的投射模式

具體地說我試圖作爲[U]函數,其描述讀取使用方法: 「返回其中每個記錄已被映射到指定的類型的新數據集 用於映射的列的方法,取決於類型U

原則上這正是我想要的,但我無法讓它工作。

這是由於預期的數據的架構是從 https://github.com/apache/spark/blob/master/sql/core/src/test/scala/org/apache/spark/sql/DatasetSuite.scala



    // definition of data 
    val data = Seq(("a", 1), ("b", 2)).toDF("a", "b") 

採取一個簡單的例子:

 

    root 
    |-- a: string (nullable = true) 
    |-- b: integer (nullable = false) 

我想投的「B」列翻番。所以我嘗試以下方法:



    import session.implicits._; 

    println(" --------------------------- Casting using (String Double)") 

    val data_TupleCast=data.as[(String, Double)] 
    data_TupleCast.show() 
    data_TupleCast.printSchema() 

    println(" --------------------------- Casting using ClassData_Double") 

    case class ClassData_Double(a: String, b: Double) 

    val data_ClassCast= data.as[ClassData_Double] 
    data_ClassCast.show() 
    data_ClassCast.printSchema() 

據我瞭解作爲定義[U],新DataFrames應具有以下模式

 

    root 
    |-- a: string (nullable = true) 
    |-- b: double (nullable = false) 

但輸出

 

    --------------------------- Casting using (String Double) 
    +---+---+ 
    | a| b| 
    +---+---+ 
    | a| 1| 
    | b| 2| 
    +---+---+ 

    root 
    |-- a: string (nullable = true) 
    |-- b: integer (nullable = false) 

    --------------------------- Casting using ClassData_Double 
    +---+---+ 
    | a| b| 
    +---+---+ 
    | a| 1| 
    | b| 2| 
    +---+---+ 

    root 
    |-- a: string (nullable = true) 
    |-- b: integer (nullable = false) 

這表明列「b」沒有被加倍。

我做錯了什麼提示?

順便說一句:我知道前一篇文章「如何更改Spark SQL的DataFrame中的列類型?」 (見How to change column types in Spark SQL's DataFrame?)。我知道我可以逐個更改列的類型,但是我正在尋找一種更通用的解決方案,它可以一次性更改整個數據的模式(並且我正在嘗試瞭解該流程中的Spark)。

+0

我不認爲你可以 - 在'爲[U]'API不會改變實際的類型,它只是提供了一個處理數據集的類型化的API; 「U」必須與實際類型相匹配,並且只能通過諸如「Column.cast」之類的轉換完成實際類型的更改,如鏈接問題中所述。 –

回答

4

好吧,既然功能鏈接和火花也懶的評價, 它實際上變化一次拍攝整個數據的模式,即使你把它寫成在這樣的時間改變一個列:

import spark.implicits._ 

df.withColumn("x", 'x.cast(DoubleType)).withColumn("y", 'y.cast(StringType))... 

作爲替代,我想你可以使用map做你投一氣呵成,如:

df.map{t => (t._1, t._2.asInstanceOf[Double], t._3.asInstanceOf[], ...)} 
+0

感謝您的建議,他們非常贊同我在SO上找到的其他解決方案。而且,他們非常符合我將要採用的解決方案。儘管如此,使用[u]會非常方便。我也想知道我是否應該用Encoders做一些技巧,但是我不明白爲什麼如果使用(String,Int),那麼編碼器就不需要了。 –

相關問題