比较数据框中的两列,并找到值的变化率

时间:2019-10-15 06:52:16

标签: scala dataframe apache-spark apache-spark-sql

我正在尝试比较数据框中的两列,并找出值的变化率。 我编写了一个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。

2 个答案:

答案 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))