簡體   English   中英

根據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派生一個新列:

  1. 對於四行中每行的每個元素,請檢查該元素是否存在於Map“ mapM”中
  2. 如果元素存在,則結構中的“類別”將是映射M中的對應值。如果元素不存在於映射M中,則類別應為null。
  3. 結構中的“相關性”應為該列從左到右的順序:P-> 1,Q-> 2,R-> 3,S-> 4。
  4. 然后,將由這四個結構形成的數組添加到提供的數據幀上的新列中。

我是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.

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