Учитывая набор данных, как вы видите в коде ниже (df), мое требование - иметь возможность добавить производный столбец (DerivedCol). Значение этого столбца является постоянным для группы строк idcol и получается путем применения а) предиката к значению другого столбца (здесь filter), а затем б) функции агрегирования (max используется здесь) над соответствующей группой.

val df = Seq(("id1","k1","7"),("id2","k1","5"),("id1","k3","2"),("id3","k1","4"),("id2","k5","1"),("id4","k5","1"))
  .toDF("idcol","keycol","valcol")

val aggDf = df.filter($"keycol" === "k1")
  .select($"idcol",$"valcol")
  .groupBy($"idcol")
  .agg(max($"valcol".cast(IntegerType)).cast(StringType).as("DerivedCol"))
  .withColumnRenamed("idcol", "newidcol")

df.join(aggDf, df("idcol") === aggDf("newidcol"), "left_outer")
  .drop(aggDf("newidcol"))

Я использую для этого left outer join. Мой набор данных очень огромен (миллионы строк). У меня есть следующие вопросы:

  1. Есть ли другой подход к этому?
  2. Какую логику разделения следует использовать, чтобы уменьшить количество случайных перемещений?

Мощность столбца idcol очень высока. Версия Spark - 2.1.1.

0
sujit 11 Сен 2018 в 12:56

1 ответ

Лучший ответ

Есть ли другой подход к этому?

Есть - оконные функции.

import org.apache.spark.sql.functions.max
import org.apache.spark.sql.expressions.Window

df.withColumn(
   "derivedcol",  
   max($"valcol".cast(IntegerType)).over(Window.partitionBy($"idcol")
)

В зависимости от:

  • Мощность - высокая мощность - это хорошо.
  • Распределение размеров групп - небольшие группы без больших положительных перекосов хороши.

Это может вести себя несколько лучше или намного хуже, чем агрегация с последующим объединением.

Какую логику разделения следует использовать, чтобы уменьшить количество случайных перемещений?

Наверное, нет. Причин как минимум две:

  • Если у вас большое количество небольших групп, оконные функции подойдут, и нет необходимости в дополнительном разбиении.
  • Если у вас небольшое количество больших групп, данные должны транслироваться, и единственное перемешивание требуется для агрегирования.
  • Если имеется большое количество больших групп - вы можете рассмотреть возможность предварительного разделения по идентификатору, но в зависимости от количества факторов вы можете как потерять, так и получить, и отсутствие дополнительного перемешивания (разбиения) в среднем лучше.
1
user10346849user10346849 11 Сен 2018 в 10:25