我试图比较两个不同列中的整数包装数组,并将评级作为字符串:
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()类型定义是否错误,并感谢任何纠正错误的指导。
答案 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"
}
}