2016-11-14 57 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)'反转排序的方向 –