Нулевые значения кадра данных преобразуются в 0 после UDF.Зачем? - PullRequest
0 голосов
/ 19 сентября 2018

Как можно обрабатывать пустые значения при обращении к значениям Row?Действительно ли исключение нулевого указателя нужно обрабатывать вручную?Должно быть лучшее решение.

case class FirstThing(id:Int, thing:String, other:Option[Double])

val df = Seq(FirstThing(1, "first", None), FirstThing(1, "second", Some(2)), FirstThing(1, "third", Some(3))).toDS
df.show

val list = df.groupBy("id").agg(collect_list(struct("thing", "other")).alias("mylist"))
list.show(false)

Это терпит неудачу с NPE:

val xxxx = udf((t:Seq[Row])=> t.map(elem => elem.getDouble(1)))
list.withColumn("aa", xxxx(col("mylist"))).show(false)

Это странно дает 0:

val xxxx = udf((t:Seq[Row])=> t.map(elem => elem.getAs[Double]("other")))
list.withColumn("aa", xxxx(col("mylist"))).show(false)

+---+-----------------------------------------+---------------+
|id |mylist                                   |aa             |
+---+-----------------------------------------+---------------+
|1  |[[first,null], [second,2.0], [third,3.0]]|[0.0, 2.0, 3.0]|
+---+-----------------------------------------+---------------+

К сожалению, этот подход работает нормальнос фреймами данных / наборами данных также происходит сбой:

val xxxx = udf((t:Seq[Row])=> t.map(elem => elem.getAs[Option[Double]]("other")))
list.withColumn("aa", xxxx(col("mylist"))).show(false)

ClassCastException: java.lang. Double не может быть приведен к scala.Option

1 Ответ

0 голосов
/ 19 сентября 2018

Использование getAs[Double] и завертывание его в Option даст ожидаемый результат:

val xxxx = udf((t: Seq[Row])=> t.map(elem => Option(elem.getAs[Double]("other"))))
list.withColumn("aa", xxxx($"mylist")).show(false)

+---+-----------------------------------------+----------------+
|id |mylist                                   |aa              |
+---+-----------------------------------------+----------------+
|1  |[[first,null], [second,2.0], [third,3.0]]|[null, 2.0, 3.0]|
+---+-----------------------------------------+----------------+

Причина, по которой getAs[Option[Double]] не работает, может заключаться в том, что схема данных не сохраняет знаниячто у колонки есть варианты.Схема перед udf:

root
 |-- id: integer (nullable = false)
 |-- mylist: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- thing: string (nullable = true)
 |    |    |-- other: double (nullable = true)
...