2016-11-14 58 views
2

我有一個數據幀格式化如下的數組:按日期排序火花數據幀列

+---+------------------------------------------------------+ 
|Id |DateInfos            | 
+---+------------------------------------------------------+ 
|B |[[3, 19/06/2012-02.42.01], [4, 17/06/2012-18.22.21]] | 
|A |[[1, 15/06/2012-18.22.16], [2, 15/06/2012-09.22.35]] | 
|C |[[5, 14/06/2012-05.20.01]]       | 
+---+------------------------------------------------------+ 

我想DateInfos列的每個元件按日期與我的陣列的第二元件的時間戳排序

root 
|-- C1: string (nullable = true) 
|-- C2: array (nullable = true) 
| |-- element: struct (containsNull = true) 
| | |-- _1: integer (nullable = false) 
| | |-- _2: string (nullable = false) 

我想我必須創建:

+---+------------------------------------------------------+ 
|Id |DateInfos            | 
+---+------------------------------------------------------+ 
|B |[[4, 17/06/2012-18.22.21], [3, 19/06/2012-02.42.01]] | 
|A |[[2, 15/06/2012-09.22.35], [1, 15/06/2012-18.22.16]] | 
|C |[[5, 14/06/2012-05.20.01]]       | 
+---+------------------------------------------------------+ 

下面我數據框的模式打印使用具有以下簽名的功能的udf:

def sort_by_date(mouvements : Array[Any]) : Array[Any] 

你有什麼想法嗎?

回答

3

這確實有點棘手 - 因爲雖然UDF的輸入和輸出類型看起來完全相同,但我們不能真正這樣定義它 - 因爲輸入實際上是mutable.WrappedArray[Row],輸出不能使用否則Spark將會無法對它進行解碼一排...

所以我們定義了一個UDF,需要一個mutable.WrappedArray[Row],並返回一個Array[(Int, String)]

val sortDates = udf { arr: mutable.WrappedArray[Row] => 
    arr.map { case Row(i: Int, s: String) => (i, s) }.sortBy(_._2) 
} 

val result = input.select($"Id", sortDates($"DateInfos") as "DateInfos") 

result.show(truncate = false) 
// +---+--------------------------------------------------+ 
// |Id |DateInfos           | 
// +---+--------------------------------------------------+ 
// |B |[[4,17/06/2012-18.22.21], [3,19/06/2012-02.42.01]]| 
// |A |[[2,15/06/2012-09.22.35], [1,15/06/2012-18.22.16]]| 
// |C |[[5,14/06/2012-05.20.01]]       | 
// +---+--------------------------------------------------+ 
+0

非常感謝您 –

+0

添加 - 號,像這樣'改編。 map {case Row(i:Int,s:String)=>(i,s)} .sortBy( -_._ 2)'反轉排序的方向 –