我正在尝试比较数据框中的两列,并找出值的变化率。 我编写了一个UDF来实现此目的,但是在执行时却出错。
下面是数据框中的数据结构。
+------------+-------------+-----------+------+
| NUM_ID | TIME |PREVIOUS_SG1|SG1_V|
+------------+-------------+-----------+------+
|XXXXX01 |1570167499000| null |79.0 |
|XXXXX01 |1570167502000| 79.0 |88.0 |
|XXXXX01 |1570167503000| 88.0 |99.0 |
|XXXXX01 |1570179810000| 99.0 |null |
|XXXXX01 |1570179811000| null |100.0 |
下面是此数据框的架构。
scala> castDF.printSchema
root
|-- NUM_ID: string (nullable = true)
|-- TIME: long (nullable = true)
|-- PREVIOUS_SG1: double (nullable = true)
|-- SG1_V: double (nullable = true)
下面是编写的UDF。
def UDF_D:UserDefinedFunction=udf((PREV: Double,CURR: Double)=>{
if(PREV != null || PREV !=0){
val out = ((CURR-PREV)/PREV)*100
out
}})
和调用UDF的scala代码
val diffDF = castDF.withColumn("SG1_DIFF", (UDF_D(col("PREVIOUS_SG1"),col("SG1_V"))))
在执行过程中,我遇到错误。
scala> val diffDF = castDF.withColumn("SG1_DIFF", (UDF_D(col("PREVIOUS_SG1"),col("SG1_V"))))
java.lang.UnsupportedOperationException: Schema for type AnyVal is not supported
是否可以进行任何强制转换以调用UDF,或者是否为空值导致了问题?我希望我传递Double值,并且不要处理任何其他Type。
答案 0 :(得分:1)
不需要任何强制转换即可调用UDF,但是UDF和列类型应同步。同样,空值也不会引起问题。
问题出在UDF中,UDF应该始终返回一个值。当输入数据为null或0时,在UDF中添加else条件;
def UDF_D: UserDefinedFunction = udf((PREV: Double, CURR: Double) => {
if (PREV != null || PREV != 0 || CURR != null || CURR != 0) {
val out = ((CURR - PREV) / PREV) * 100
out
} else 0
})
答案 1 :(得分:1)
您无需udf即可
df.select(when(('PREV.isNull || 'CURR === 0), (('CURR-'PREV)/'PREV)*100).otherwise(0))
并作为功能
def compareCols(PREV: Column, CURR: Column): Column = {
when((PREV.isNull || CURR === 0), ((CURR-PREV)/PREV)*100).otherwise(0)
}
val diffDF = df.withColumn("SG1_DIFF", compareCols('PREV,'CURR))