簡體   English   中英

如何將 Array[Seq[String]] 傳遞給 apache spark udf? (錯誤:不適用)

[英]How to pass Array[Seq[String]] to apache spark udf? (Error: Not Applicable)

我在 Scala 中有以下 apache spark udf:

val myFunc = udf {
  (userBias: Float, otherBiases: Map[Long, Float],
    userFactors: Seq[Float], context: Seq[String]) => 
    var result = Float.NaN

    if (userFactors != null) {
      var contexBias = 0f

      for (cc <- context) {
       contexBias += otherBiases(contextMapping(cc))
      }

      // definition of result
      // ...
    }
    result
}

現在我想將參數傳遞給這個函數,但是由於參數context ,我總是收到消息 Not Applicable 。 我知道用戶定義的函數按行輸入,如果我刪除context ,這個函數就會運行......如何解決這個問題? 為什么它不從Array[Seq[String]]讀取行,即從context 或者,將context作為DataFrame或類似的東西傳遞也是可以接受的。

// context is Array[Seq[String]]
val a = sc.parallelize(Seq((1,2),(3,4))).toDF("a", "b")
val context = a.collect.map(_.toSeq.map(_.toString))

// userBias("bias"), otherBias("biases") and userFactors("features")
// have a type Column, while userBias... are DataFrames
myDataframe.select(dataset("*"),
                   myFunc(userBias("bias"),
                          otherBias("biases"),
                          userFactors("features"),
                          context)
                   .as($(newCol)))

更新:

我嘗試了zero323的答案中指出的解決方案,但是context: Array[Seq[String]]仍然存在一個小問題context: Array[Seq[String]] 特別是問題在於循環遍歷此數組for (cc <- context) { contexBias += otherBiases(contextMapping(cc)) } 我應該將 String 傳遞給contextMapping ,而不是Seq[String]

  def myFunc(context: Array[Seq[String]]) = udf {
    (userBias: Float, otherBiases: Map[Long, Float],
     userFactors: Seq[Float]) =>
      var result = Float.NaN

      if (userFactors != null) {
        var contexBias = 0f
        for (cc <- context) {
          contexBias += otherBiases(contextMapping(cc))
        }

        // estimation of result

      }
      result
  }

現在我這樣稱呼它:

myDataframe.select(dataset("*"),
                   myFunc(context)(userBias("bias"),
                                   otherBias("biases"),
                                   userFactors("features"))
           .as($(newCol)))

火花 2.2+

您可以使用typedLit函數:

import org.apache.spark.sql.functions.typedLit

myFunc(..., typedLit(context))

火花 < 2.2

直接傳遞給 UDF 的任何參數都必須是Column因此如果您想傳遞常量數組,則必須將其轉換為列文字:

import org.apache.spark.sql.functions.{array, lit}

val myFunc: org.apache.spark.sql.UserDefinedFunction = ???

myFunc(
  userBias("bias"),
  otherBias("biases"),
  userFactors("features"),
  // org.apache.spark.sql.Column
  array(context.map(xs => array(xs.map(lit _): _*)): _*)  
)

Column對象只能使用閉包間接傳遞,例如:

def myFunc(context: Array[Seq[String]]) = udf {
  (userBias: Float, otherBiases: Map[Long, Float],  userFactors: Seq[Float]) => 
    ???
}

myFunc(context)(userBias("bias"), otherBias("biases"), userFactors("features"))

另一種方法是使用結構

val seq: Seq[String] = ...
val func: UserDefinedFunction = udf((seq: Row) => ...)
val seqStruct = struct(seq.map(v => lit(v)): _*)
func(seqStruct)

暫無
暫無

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

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