Spark序列[int]与[String]序列输出

时间:2016-12-23 13:18:37

标签: arrays scala apache-spark udf

我试图比较两个不同列中的整数包装数组,并将评级作为字符串:

import org.apache.spark.sql.Row
import org.apache.spark.sql.functions._
import scala.collection.mutable.WrappedArray

DataFrame数据的列A和B包含我想要比较的包装数组:

val data = Seq(
    (Seq(1,2,3),Seq(4,5,6),Seq(7,8,9)),
    (Seq(1,1,3),Seq(6,5,7),Seq(11,9,8))
    ).toDF("A","B","C")

以下是它的样子:

data: org.apache.spark.sql.DataFrame = [A: array<int>, B: array<int> ... 1 more field]
+---------+---------+----------+
|        A|        B|         C|
+---------+---------+----------+
|[1, 2, 3]|[4, 5, 6]| [7, 8, 9]|
|[1, 1, 3]|[6, 5, 7]|[11, 9, 8]|
+---------+---------+----------+

然后这是用户定义函数,我想比较每行A列和B列中成对数组中的每个元素,并给出简单逻辑的评级。例如,如果A(1)> B(1)然后D(1)是&#34; Top&#34;。所以作为D列的第一行,我希望有[&#34; Top&#34;,&#34; Top&#34;,&#34; Top&#34;]

def myToChar(num1: Seq[Int], num2: Seq[Int]): Seq[String] = {
        val twozipped = num1.zip(num2)
        for ((x,y) <- num1.zip(num2)) {
          if (x > y)  "Top"
          if (x < y)  "Well"
          if (x == y)  "Good"
    }}


val udfToChar = udf(myToChar(_: Seq[Int], _: Seq[Int]))

val ouput = data.withColumn("D",udfToChar($"A",$"B"))

但是,我一直收到<console>:45: error: type mismatch;错误信息。不确定我的udf()类型定义是否错误,并感谢任何纠正错误的指导。

1 个答案:

答案 0 :(得分:1)

您的myToChar定义被声明为返回Seq[String] - 但其实现没有 - 它返回Unit,因为for表达式(没有yield }}子句具有Unit类型。

您可以通过修复函数的实现来解决此问题:

  • for替换为map操作
  • 将最后一个if替换为else,否则映射函数也会返回Unit以获取不符合if条件的输入(与模式匹配不同,编译器可以'得出结论,你的if条件是详尽无遗的 - 它必须假设它们也有可能不成立:)

所以 - 正确的实施将是:

def myToChar(num1: Seq[Int], num2: Seq[Int]): Seq[String] = {
  num1.zip(num2).map { case (x, y) =>
    if (x > y) "Top"
    if (x < y) "Well"
    else "Good"
  }
} 

或者使用与守卫的模式匹配:

def myToChar(num1: Seq[Int], num2: Seq[Int]): Seq[String] = {
  num1.zip(num2).map {
    case (x, y) if x > y => "Top"
    case (x, y) if x < y => "Well"
    case _ => "Good"
  }
}