Меньшая или равная ошибка синтаксиса сравнения - PullRequest
0 голосов
/ 28 июня 2018

Мой UDF сравнивается, если разница во времени между двумя столбцами не превышает 5 дней. Если используется оператор ==, выражение компилируется правильно, но <= (или <code>lt) завершается с ошибкой несоответствия типов. Код:

val isExpiration : (Column, Column, Column) =>
Column = (BCED, termEnd, agrEnd) =>
{
   if(abs(datediff(if(termEnd == null) {agrEnd} else {termEnd}, BCED)) lt 6)
      {lit(0)}
else
      {lit(1)}
}

Ошибка:

notebook:3: error: type mismatch;
 found   : org.apache.spark.sql.Column
 required: Boolean
    if(abs(datediff(if(termEnd == null) {agrEnd} else {termEnd}, BCED)) lt 6) {lit(0)}...
                                                                        ^

Должно быть, я упускаю что-то очевидное - кто-нибудь может посоветовать, как проверить, если Столбец значение меньше или равно константе?

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Это потому, что abs(col).lt(6) возвращает объект типа Column, а if ожидает, что условие будет оценено как true или false, который имеет тип Scala Boolean.

Кроме того, UDF не работает с Column типом данных, он работает с объектами Scala (Int, String, Boolean и т. Д.)

Поскольку все, что вы делаете - это используете функции Spark SQL, вы можете переписать свой UDF следующим образом:

val isExpiration = (
    when(
        abs(datediff(coalesce($"termEnd", $"agrEnd") , $"BCED")) <= 6, lit(0)
    ).otherwise(lit(1))
)

И использование будет:

df.show
//+----------+----------+----------+
//|      BCED|   termEnd|    agrEnd|
//+----------+----------+----------+
//|2018-06-10|2018-06-25|2018-06-25|
//|2018-06-10|      null|2018-06-15|
//+----------+----------+----------+


df.withColumn("x", isExpiration).show
//+----------+----------+----------+---+
//|      BCED|   termEnd|    agrEnd|  x|
//+----------+----------+----------+---+
//|2018-06-10|2018-06-25|2018-06-25|  1|
//|2018-06-10|      null|2018-06-15|  0|
//+----------+----------+----------+---+
0 голосов
/ 28 июня 2018

Похоже, вы смешали функции udf и Spark, вам нужно использовать только одну из них. Когда это возможно, всегда предпочтительнее использовать , а не , а udf, поскольку они не могут быть оптимизированы (и, следовательно, обычно медленнее). Без udf это можно сделать следующим образом:

df.withColumn("end", when($"termEnd".isNull, $"agrEnd").otherwise($"termEnd"))
  .withColumn("expired", when(abs(datediff($"end", $"BCED")) lt 6, 0).otherwise(1))

Я ввел временный столбец, чтобы сделать код немного более читабельным.


Используя udf, это можно сделать, например, следующим образом:

val isExpired = udf((a: Date, b: Date) => {
  if ((math.abs(a.getTime() - b.getTime()) / (1000 * 3600 * 24)) < 6) { 
    0
  } else { 
    1
  }
})

df.withColumn("end", when($"termEnd".isNull, $"agrEnd").otherwise($"termEnd"))
  .withColumn("expired", isExpired($"end", $"BCED"))

Здесь я снова использовал временный столбец, но эту логику можно перенести в udf, если хотите.

...