簡體   English   中英

獲取Spark Dataframe列中列表的最后一個元素

[英]Get last element of list in Spark Dataframe column

我有一個具有以下架構的DataFrame

root
 |-- memberId: long (nullable = true)
 |-- items: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- timestamp: long (nullable = true)
 |    |    |-- itemId: integer (nullable = true)
 |    |    |-- weight: double (nullable = true)

說,DataFrame(稱為df )看起來像這樣。

+-----------+------------------------------------------------------------------------+
|memberId   |items                                                                   |
+-----------+------------------------------------------------------------------------+
|10000000001|[[1234567891, 104, 1.0], [1234567892, 103, 3.0]]                        |
|10000000002|[[1234567891, 103, 1.0], [1234567893, 102, 1.0], [1234567894, 101, 2.0]]|
+-----------+------------------------------------------------------------------------+

可以看出, dfmemberIdstruct list的映射。 我想對其進行轉換,以便檢索對應於每個成員的struct列表中的最后一個元素。 因此,產生的DataFrame應該看起來像

+-----------+----------------------+
|memberId   |lastItem              |
+-----------+----------------------+
|10000000001|[1234567892, 103, 3.0]|
|10000000002|[1234567894, 101, 2.0]|
+-----------+----------------------+

我試過了

val newDf = df
  .withColumn("lastItem", last($"items"))
  .drop("items")

但這僅引發以下形式的異常:

grouping expressions sequence is empty, 
and '`memberId`' is not an aggregate function. 
Wrap '(last(`items`, false) AS `item`)' in 
windowing function(s) or wrap '`memberId`' in 
first() (or first_value) if you don't care which value you get

我相信發生這種情況是因為last是一個aggregation函數,並且要求我在調用last之前使用.groupBy("memberId")

我怎樣才能做到這一點? 在使用DataFrame時,不鼓勵使用UDF ,但是我找不到能完成我打算做的事情的本機函數。

您可以使用array類型的Columnapply方法來執行此操作,通過它可以訪問數組元素:

val newDf = df
.withColumn("lastItem", $"items"(size($"items")-1))
.drop("items")

編輯:

要獲得前n-1個項目,我將使用UDF:

val sliceUDF = udf((arr:Seq[Row],from:Int,to:Int) => arr.slice(from,to).map{case Row(ts:Long,Id:Int,w:Double) => (ts,Id,w)})

val newDf = df
  .withColumn("subItems", sliceUDF($"items",lit(0),size($"items")-1))
  .drop("items")

也許也可以使用純DataFrame API來完成,但是我認為這會相當復雜(例如,結合使用posexplode ,window-function和collect_list

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM