2016-12-20 44 views
3

我遇到了Spark Scala腳本的一個小問題。基本上我有原始數據,我正在做分組和計數等聚合後,我想將輸出保存爲特定的JSON格式。Spark Dataframe架構定義使用帶案例類和列名別名的反射

編輯:

我試圖簡化的問題,並改寫它:

當我選擇與Array[org.apache.spark.sql.Column]其中的列名有別名,然後使用列名從源數據幀的數據(或當試圖將行映射到case類時,我得到一個「Task not serializable」異常。

var dm = sqlContext.createDataFrame(Seq((1,"James"),(2,"Anna"))).toDF("id", "name") 

val cl = dm.columns 
val cl2 = cl.map(name => col(name).as(name.capitalize)) 
val dm2 = dm.select(cl2:_*) 
val n = "Name" 
case class Result(Name:String) 
val r = dm2.map(row => Result(row.getAs(n))).toDF 

,第二部分或問題,我實際需要的最終模式是這些Result類對象的數組。我還沒有想出,如何做到這一點。預期的結果應該有一個這樣的模式:

case class Test(var FilteredStatistics: Array[Result]) 
    val t = Test(Array(Result("Anna"), Result("James"))) 

    val t2 = sc.parallelize(Seq(t)).toDF 

    scala> t2.printSchema 
    root 
    |-- FilteredStatistics: array (nullable = true) 
    | |-- element: struct (containsNull = true) 
    | | |-- Name: string (nullable = true) 

TL; DR

  1. 如何數據幀行映射到一個案例類對象時,數據框列有別名和變量用於列名?

  2. 如何將這些case類對象添加到數組?

+0

序列化問題沒有重現 - 我複製了所有的代碼,它適用於我。看起來像代碼中的某個地方(不粘貼在這裏?),您正在使用DataFrame中使用的Case類中的org.apache.spark.sql.Column對象,或者在序列化併發送給工作人員的轉換中使用... –

+2

順便說一句 - 我們中的一個可能會迷失在這個非常複雜的問題的細節中......嘗試最小化它(很多) - 找到再現問題的最簡單的例子(在類似的最小化後分別詢問另一個問題) –

+0

one修復嘗試你的序列化問題...... class Result(???)extends Serializable;對象結果{def apply(r:Row):結果= r匹配{??? }}然後在r上使用模式匹配來處理你在DF中可能有的各種格式。當你試圖將一個類應用到行的一部分時,通常會遇到問題,但是如果創建了一個可以映射整行的類......那麼'DF.map(Result)'可能會起作用。 – kmh

回答

0

序列化問題:這裏的問題是val n = "Name":它被傳遞到RDD變換(dm2.map(...))一個匿名函數,這使得火花接近超過該變量和含有它範圍內使用,其中還包括cl2,其類型爲Array[Column],因此它不是可序列化的。

解決方案很簡單 - 要麼內嵌n(要獲得dm2.map(row => Result(row.getAs("Name")))),要麼將其置於Serializable上下文(一個對象或不包含任何不可序列化成員的類)中。

+0

好的,我仍然有一些困難。我不想這樣做,因爲我在一個地方聲明瞭列名,然後在整個代碼中使用它們。我不想複製它們,因爲那樣我就不得不在多個地方改變它們。但是你是否意味着我應該創建一個對象或類來保存必要的變量?我嘗試了'對象Params extends Serializable {val name =「Name」}'和'case class Params(name:String)'(案例類應該是默認可序列化的)並且在getAs中使用'Params.name',沒有幫助。對不起,如果我錯過了明顯的東西 –

+0

如果對象沒有嵌套在任何其他類 - 它應該工作(爲我工作...)。請注意,當您在* spark-shell *中創建對象時,它們實際上嵌套在封裝整個shell代碼的對象中,所以它可能無法在那裏工作(我認爲) –