[英]Flattening the array of a dataframe column into separate columns and corresponding values in Spark scala
[英]Add derived column (as array of struct) based on values and ordering of other columns in Spark Scala dataframe
我有一個Scala Spark數據框,其中有四列(所有字符串類型)-P,Q,R,S-和主鍵(稱為PK)(整數類型)。
這4列中的每一個都可以具有空值。 列從左到右的順序是列的重要性/相關性,需要保留。 基本數據幀的結構保持與所示相同。
我希望最終輸出如下:
root
|-- PK: integer (nullable = true)
|-- P: string (nullable = true)
|-- Q: string (nullable = true)
|-- R: string (nullable = true)
|-- S: string (nullable = true)
|-- categoryList: array (nullable = true)
| |-- myStruct: struct (nullable = true)
| | |-- category: boolean (nullable = true)
| | |-- relevance: boolean (nullable = true)
我需要基於以下算法從4列P,Q,R,S派生一個新列:
我是Scala的新手,到目前為止,這里是我擁有的東西:
case class relevanceCaseClass(category: String, relevance: Integer)
def myUdf = udf((code: String, relevance: Integer) => relevanceCaseClass(mapM.value.getOrElse(code, null), relevance))
df.withColumn("newColumn", myUdf(col("P/Q/R/S"), 1))
問題是我無法在withColumn函數內部傳遞排序的值。 我需要讓myUdf函數知道相關性的值。 我是從根本上做錯了嗎?
因此,我應該得到輸出:
PK P Q R S newCol
1 a b c null array(struct("a", 1), struct(null, 2), struct("c", 3), struct(null, 4))
此處,在地圖中找不到值“ b”,因此(對於類別)該值為空。 由於列S的值已經為空,因此保持為空。 相關性是根據左右列的順序排列的。
給定一個輸入數據幀 (在OP中進行測試)為
+---+---+---+---+----+
|PK |P |Q |R |S |
+---+---+---+---+----+
|1 |a |b |c |null|
+---+---+---+---+----+
root
|-- PK: integer (nullable = false)
|-- P: string (nullable = true)
|-- Q: string (nullable = true)
|-- R: string (nullable = true)
|-- S: null (nullable = true)
廣播的地圖為
val mapM = spark.sparkContext.broadcast(Map("a" -> "a", "c" -> "c"))
您可以定義udf
函數和調用udf
功能如下
def myUdf = udf((pqrs: Seq[String]) => pqrs.zipWithIndex.map(code => relevanceCaseClass(mapM.value.getOrElse(code._1, "null"), code._2+1)))
val finaldf = df.withColumn("newColumn", myUdf(array(col("P"), col("Q"), col("R"), col("S"))))
與OP中的案例類別相同
case class relevanceCaseClass(category: String, relevance: Integer)
這應該給您您想要的輸出,即finaldf
將是
+---+---+---+---+----+--------------------------------------+
|PK |P |Q |R |S |newColumn |
+---+---+---+---+----+--------------------------------------+
|1 |a |b |c |null|[[a, 1], [null, 2], [c, 3], [null, 4]]|
+---+---+---+---+----+--------------------------------------+
root
|-- PK: integer (nullable = false)
|-- P: string (nullable = true)
|-- Q: string (nullable = true)
|-- R: string (nullable = true)
|-- S: null (nullable = true)
|-- newColumn: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- category: string (nullable = true)
| | |-- relevance: integer (nullable = true)
我希望答案是有幫助的
您可以將多個列傳遞給udf作為以下示例代碼
case class Relevance(category: String, relevance: Integer)
def myUdf = udf((p: String,q: String,s: String,r: String) => Seq(
Relevance(mapM.value.getOrElse(p, null), 1),
Relevance(mapM.value.getOrElse(q, null), 2),
Relevance(mapM.value.getOrElse(s, null), 3),
Relevance(mapM.value.getOrElse(r, null), 4)
))
df.withColumn("newColumn", myUdf(df("P"),df("Q"),df("S"),df("R")))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.