Size: a a a

2020 December 16

ПФ

Паша Финкельштейн... in Moscow Spark
Алексей
ну ладно, воспользовался воркэраундом agg_cols.head, agg_cols.tail: _* , но причина такой сигнатуры функции для меня остается загадкой
ну моя гипотеза как раз заключается в том, что если мы не запрашиваем ни одной колонки на выходе — то зачем мы всё эт творим?
источник

ПФ

Паша Финкельштейн... in Moscow Spark
У селекта одна из сигнатур такая же
источник

А

Алексей in Moscow Spark
Паша Финкельштейн
У селекта одна из сигнатур такая же
тогда не понимаю как тогда у меня работает это:
sku_df.groupBy(gr_cols:_*).agg(agg_cols.head, agg_cols.tail: _*).as("sku").select(sel_cols:_*)
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Алексей
тогда не понимаю как тогда у меня работает это:
sku_df.groupBy(gr_cols:_*).agg(agg_cols.head, agg_cols.tail: _*).as("sku").select(sel_cols:_*)
вторая не такая потому что
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Тут скорее вопрос в том, какой смысл в селекте без аргументов
источник

А

Алексей in Moscow Spark
не проверял, возможно, *
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Алексей
не проверял, возможно, *
но такое поведение для agg дорого стоит. Селект — у тебя все данные и так уже есть. Но  это всё спекуляции конечно
источник

А

Алексей in Moscow Spark
не, select(List():_*) , возвращает фрейм без колонок
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Алексей
не, select(List():_*) , возвращает фрейм без колонок
ну вот, в случае agg за нас просто подумали, кажется. Ежели бы в скале были зависимые типы — можно было бы сказать "Сюда принимается варарг размером не меньше 1"
источник

ФМ

Федор Мануковский... in Moscow Spark
Алексей
Подскажите, почему в agg нельзя писать просто list:_*  , как в остальных функциях?
df.groupBy(gr_cols:_*).agg(agg_cols: _*)
Приходится извращаться с
sku_df.groupBy(gr_cols:_*).agg(agg_cols.head, agg_cols.tail: _*)
А это не чтобы сигнатуры для string и column отличались?(важно при 0 аргументов)
источник

GP

Grigory Pomadchin in Moscow Spark
Паша Финкельштейн
ну вот, в случае agg за нас просто подумали, кажется. Ежели бы в скале были зависимые типы — можно было бы сказать "Сюда принимается варарг размером не меньше 1"
не нужны зависимые, рефайнд типов хватит, а в данном случае нон емпти списка
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Grigory Pomadchin
не нужны зависимые, рефайнд типов хватит, а в данном случае нон емпти списка
Тоже верно
источник

ФМ

Федор Мануковский... in Moscow Spark
Федор Мануковский
А это не чтобы сигнатуры для string и column отличались?(важно при 0 аргументов)
а, не, это относится только к select
источник
2020 December 17

ИК

Иван Калининский... in Moscow Spark
Паша Финкельштейн
ds.groupBy().agg(Map("age" -> "max", "salary" -> "avg"))
В скаладоке написано с версии 1.3
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Иван Калининский
В скаладоке написано с версии 1.3
Хм. В моей с 2.0.0...
источник

ИК

Иван Калининский... in Moscow Spark
Алексей
Подскажите, почему в agg нельзя писать просто list:_*  , как в остальных функциях?
df.groupBy(gr_cols:_*).agg(agg_cols: _*)
Приходится извращаться с
sku_df.groupBy(gr_cols:_*).agg(agg_cols.head, agg_cols.tail: _*)
В исходниках содержится ответ на вопрос, и, спойлер, @asm0dey в целом прав, но судит разработчиков с высоты своего уровня (то есть, переоценивает обдуманность решений). Я скопирую часть скаладока и сигнатуру agg из класса org.apache.spark.sql.RelationalGroupedDataset:
/**
….
* Note that before Spark 1.4, the default behavior is to NOT retain grouping columns. To change
* to that behavior, set config variable spark.sql.retainGroupColumns to false.
* {{{
*   // Scala, 1.3.x:
*   df.groupBy("department").agg($"department", max("age"), sum("expense"))
*
*   // Java, 1.3.x:
*   df.groupBy("department").agg(col("department"), max("age"), sum("expense"));
* }}}
*
* @since 1.3.0
*/
spark.sql.retainGroupColumns to false.
* {{{
*   // Scala, 1.3.x:
*   df.groupBy("department").agg($"department", max("age"), sum("expense"))
*
*   // Java, 1.3.x:
*   df.groupBy("department").agg(col("department"), max("age"), sum("expense"));
* }}}
*
* @since @since 1.3.0
*/
@scala.annotation.varargs
def agg(expr: Column, exprs: Column*): DataFrame = {???}

Класс до 2.0.0 назывался GroupedData. Методы agg в классе org.apache.spark.sql.Dataset являются обертками для вызова groupBy() и последующего обращения к методу agg из класса RelationalGroupedDataset

Как видим, в 1.3.0 колонки, по которым шла группировка не выводились, поэтому, чтобы привыкшие к ораклу и прочим SQL RDBMS пользователи не фрустрировали, нужна была подсказка, чтобы они не забывали выводить группируемые колонки, если они вообще присутствуют
Варианты agg с Map[String, String] c 1.3.0 выводили групповые поля, поэтому сразу же шли в сигнатуре, допускающей передачу пустого списка

Можно подумать, что это сделано, чтобы пользователи не забывали писать хотя бы одно выражение для группировки, если агрегация выполняется на всем наборе данных. Например, count(*) на пустом датафрейме должен выдать датафрейм с одной строкой и значением 0, а не пустой датафрейм с полем count. Но agg c пустым Map вполне валидно выполняется и выводит совершенно пустой датафрейм, значит, внутренних препятствий для такого использования не было, и даже можно быстро написать класс, который будет вызывать именно такую операцию без обращения к промежуточным agg
источник

ИК

Иван Калининский... in Moscow Spark
https://scastie.scala-lang.org/Ebde1Dx2S0SJHxvqaFvntQ

Вот реализация такого класса, работать будет, если правильно оформить пакет и т.д. Я не освоил scastie кроме как для стандартной библиотеки(
источник

ПФ

Паша Финкельштейн... in Moscow Spark
Иван Калининский
В исходниках содержится ответ на вопрос, и, спойлер, @asm0dey в целом прав, но судит разработчиков с высоты своего уровня (то есть, переоценивает обдуманность решений). Я скопирую часть скаладока и сигнатуру agg из класса org.apache.spark.sql.RelationalGroupedDataset:
/**
….
* Note that before Spark 1.4, the default behavior is to NOT retain grouping columns. To change
* to that behavior, set config variable spark.sql.retainGroupColumns to false.
* {{{
*   // Scala, 1.3.x:
*   df.groupBy("department").agg($"department", max("age"), sum("expense"))
*
*   // Java, 1.3.x:
*   df.groupBy("department").agg(col("department"), max("age"), sum("expense"));
* }}}
*
* @since 1.3.0
*/
spark.sql.retainGroupColumns to false.
* {{{
*   // Scala, 1.3.x:
*   df.groupBy("department").agg($"department", max("age"), sum("expense"))
*
*   // Java, 1.3.x:
*   df.groupBy("department").agg(col("department"), max("age"), sum("expense"));
* }}}
*
* @since @since 1.3.0
*/
@scala.annotation.varargs
def agg(expr: Column, exprs: Column*): DataFrame = {???}

Класс до 2.0.0 назывался GroupedData. Методы agg в классе org.apache.spark.sql.Dataset являются обертками для вызова groupBy() и последующего обращения к методу agg из класса RelationalGroupedDataset

Как видим, в 1.3.0 колонки, по которым шла группировка не выводились, поэтому, чтобы привыкшие к ораклу и прочим SQL RDBMS пользователи не фрустрировали, нужна была подсказка, чтобы они не забывали выводить группируемые колонки, если они вообще присутствуют
Варианты agg с Map[String, String] c 1.3.0 выводили групповые поля, поэтому сразу же шли в сигнатуре, допускающей передачу пустого списка

Можно подумать, что это сделано, чтобы пользователи не забывали писать хотя бы одно выражение для группировки, если агрегация выполняется на всем наборе данных. Например, count(*) на пустом датафрейме должен выдать датафрейм с одной строкой и значением 0, а не пустой датафрейм с полем count. Но agg c пустым Map вполне валидно выполняется и выводит совершенно пустой датафрейм, значит, внутренних препятствий для такого использования не было, и даже можно быстро написать класс, который будет вызывать именно такую операцию без обращения к промежуточным agg
Приеольно, спасибо
источник

А

Алексей in Moscow Spark
Иван Калининский
https://scastie.scala-lang.org/Ebde1Dx2S0SJHxvqaFvntQ

Вот реализация такого класса, работать будет, если правильно оформить пакет и т.д. Я не освоил scastie кроме как для стандартной библиотеки(
спасибо, но лучше оставлю workaround, чем вносить неочевидность со стандартным api через implicit
источник

ИК

Иван Калининский... in Moscow Spark
Алексей
спасибо, но лучше оставлю workaround, чем вносить неочевидность со стандартным api через implicit
можно называть функции по другому, например aggList, так неопределенность уменьшится, а обращаться можно будет как к методу класса
источник