Как назвать сводные столбцы?

Я использую Spark в Scala, и мои агрегированные столбцы анонимны. Есть ли удобный способ переименовать несколько столбцов из набора данных? Я думал о наложении схемы с as, но ключевой столбец представляет собой структуру (из-за операции groupBy), и я не могу понять, как определить case class с StructType в нем.

Я попытался определить схему следующим образом:

val returnSchema = StructType(StructField("edge", StructType(StructField("src", IntegerType, true),
                                                             StructField("dst", IntegerType), true)), 
                              StructField("count", LongType, true))
edge_count.as[returnSchema]

но я получил ошибку компиляции:

Message: <console>:74: error: overloaded method value apply with alternatives:
  (fields: Array[org.apache.spark.sql.types.StructField])org.apache.spark.sql.types.StructType <and>
  (fields: java.util.List[org.apache.spark.sql.types.StructField])org.apache.spark.sql.types.StructType <and>
  (fields: Seq[org.apache.spark.sql.types.StructField])org.apache.spark.sql.types.StructType
 cannot be applied to (org.apache.spark.sql.types.StructField, org.apache.spark.sql.types.StructField, Boolean)
       val returnSchema = StructType(StructField("edge", StructType(StructField("src", IntegerType, true),

person Emre    schedule 25.07.2016    source источник
comment
Не могли бы вы показать нам код? Так что, может быть, я могу сформулировать лучший подход?   -  person Alberto Bonsanto    schedule 26.07.2016
comment
Представьте, что у вас есть набор данных с тремя столбцами. Группируйте по первым двум и считайте по третьему. Тогда ключ является кортежем. У меня Спарк 1.6.2. Спасибо @AlbertoBonsanto!   -  person Emre    schedule 26.07.2016


Ответы (2)


Лучшее решение — явно назвать ваши столбцы, например,

df
  .groupBy('a, 'b)
  .agg(
    expr("count(*) as cnt"),
    expr("sum(x) as x"),
    expr("sum(y)").as("y")
  )

Если вы используете набор данных, вы должны указать тип ваших столбцов, например, expr("count(*) as cnt").as[Long].

Вы можете использовать DSL напрямую, но я часто нахожу его более подробным, чем простые выражения SQL.

Если вы хотите выполнять массовые переименования, используйте Map, а затем foldLeft фрейм данных.

person Sim    schedule 25.07.2016
comment
Это дает мне ошибку несоответствия типа; вход представляет собой набор данных. - person Emre; 26.07.2016
comment
Это потому, что expr() возвращает Column, а вам нужен TypedColumn в API набора данных. Я обновил ответ, чтобы показать пример набора данных. - person Sim; 26.07.2016

В итоге я использовал aliases с оператором select; например.,

ds.select($"key.src".as[Short], 
          $"key.dst".as[Short], 
          $"sum(count)".alias("count").as[Long])

Сначала мне пришлось использовать printSchema для определения имен производных столбцов:

> ds.printSchema

root
 |-- key: struct (nullable = false)
 |    |-- src: short (nullable = false)
 |    |-- dst: short (nullable = false)
 |-- sum(count): long (nullable = true)
person Emre    schedule 27.07.2016