【发布时间】:2018-06-14 10:10:21
【问题描述】:
我有一个 Spark DataFrame,其中包含我使用李克特量表与数字分数匹配的字符串。不同的问题 ID 映射到不同的分数。我正在尝试在 Apache Spark udf 中的 Scala 范围内进行模式匹配,使用这个问题作为指导:
How can I pattern match on a range in Scala?
但是当我使用范围而不是简单的 OR 语句时,我会遇到编译错误, 即
31 | 32 | 33 | 34 工作正常
31 to 35 无法编译。请问有什么我在语法上出错的地方吗?
另外,在最后一种情况下 _,我想映射到 String 而不是 Int,
case _ => "None" 但这给出了一个错误:
java.lang.UnsupportedOperationException: Schema for type Any is not supported
大概这是 Spark 的通用问题,因为完全有可能在原生 Scala 中返回 Any?
这是我的代码:
def calculateScore = udf((questionId: Int, answerText: String) => (questionId, answerText) match {
case ((31 | 32 | 33 | 34 | 35), "Rarely /<br>Never") => 4 //this is fine
case ((31 | 32 | 33 | 34 | 35), "Occasionally") => 3
case ((31 | 32 | 33 | 34 | 35), "Often") => 2
case ((31 | 32 | 33 | 34 | 35), "Almost always /<br>Always") => 1
case ((x if 41 until 55 contains x), "None of the time") => 1 //this line won't compile
case _ => 0 //would like to map to "None"
})
然后在 Spark DataFrame 上使用 udf,如下所示:
val df3 = df.withColumn("NumericScore", calculateScore(df("QuestionId"), df("AnswerText")))
【问题讨论】:
-
UDF 的想法是它返回一个可以在 SQL 语句中使用的结果。因此,它需要是 Int、String 或其他支持的类型。 Any 在 SQL 上下文中没有任何意义。在这里,您正在做一些基本相似的事情,只是使用数据帧而不是直接使用 SQL。不过,如果您真的想要在通配符情况下有不同的行为(我不明白您为什么会这样做),也许您可以返回 -1 或类似的东西。或者,让其他情况返回字符串。
-
@Phasmid 我正在清理我正在对其执行分析的数据文件。该文件目前被格式化为一个长长的问题列表,我正在将这些问题作为答案。一些响应需要是字符串,其他是整数、双精度等。当我旋转数据时,我将为每个响应设置架构。所以我需要列的输出是灵活的 - 因此使用 Any。不过,使用 -1 是个好主意。
-
但我意识到使用 Any 是不可能的,所以我将使用字符串而不是整数
标签: scala apache-spark pattern-matching user-defined-functions