У меня есть заказы DataFrame:

+-----------------+-----------+--------------+
|               Id|    Order  |        Gender|
+-----------------+-----------+--------------+
|             1622|[101330001]|          Male|
|             1622|   [147678]|          Male|
|             3837|  [1710544]|          Male|
+-----------------+-----------+--------------+

Которые я хочу сгруппировать по идентификатору и полу, а затем агрегировать заказы. Я использую пакет org.apache.spark.sql.functions, и код выглядит так:

DataFrame group = orders.withColumn("orders", col("order"))
                .groupBy(col("Id"), col("Gender"))
                .agg(collect_list("products"));

Однако, поскольку столбец Order имеет тип array, я получаю это исключение, потому что он ожидает примитивный тип:

User class threw exception: org.apache.spark.sql.AnalysisException: No handler for Hive udf class org.apache.hadoop.hive.ql.udf.generic.GenericUDAFCollectList because: Only primitive type arguments are accepted but array<string> was passed as parameter 1

Я посмотрел в пакете, есть функции сортировки для массивов, но нет агрегатных функций. Есть идеи, как это сделать? Спасибо.

3
Can Arel 30 Июн 2016 в 11:07

1 ответ

Лучший ответ

В этом случае вы можете определить свою собственную функцию и зарегистрировать ее как UDF

val userDefinedFunction = ???
val udfFunctionName = udf[U,T](userDefinedFunction)

Затем вместо этого передайте этот столбец внутри этой функции, чтобы он был преобразован в примитивный тип, а затем передайте его в методе with Columns.

Что-то вроде этого:

val dataF:(Array[Int])=>Int=_.head

val dataUDF=udf[Int,Array[Int]](dataF)


DataFrame group = orders.withColumn("orders", dataUDF(col("order")))
                .groupBy(col("Id"), col("Gender"))
                .agg(collect_list("products"));

Надеюсь это работает !

1
Shivansh 30 Июн 2016 в 11:25