2016-02-05 3 views
1

Я собираю значения по параметру, как показано ниже, используя apache-spark и scala. Это добавляет значения в «Список» . Есть ли более эффективный способ получить список по ключу и StatCounter?Эффективная группировка по ключу и StatCounter

val predictorRawKey = predictorRaw.map { x => 
     val param = x._1 
     val val: Double = x._2.toDouble 
     (param, val) 
    }.mapValues(num => List(num)) 
    .reduceByKey((l1, l2) => l1 ::: l2) 
    .map { x => x._1, StatCounter(x._2.iterator)) 

ответ

1

Для начала вы не должны использовать reduceByKey для группировки значений. Более эффективно опускать агрегацию на стороне карты и напрямую использовать groupByKey.

К счастью StatCounter может работать в потоковом режиме, и нет никакой необходимости групповые ценности вообще:

import org.apache.spark.util.StatCounter 

val pairs = predictorRawKey.map(x => (x._1, x._2.toDouble)) 

val predictorRawKey = pairs.aggregateByKey(StatCounter(Nil))(
    (acc: StatCounter, x: Double) => acc.merge(x), 
    (acc1: StatCounter, acc2: StatCounter) => acc1.merge(acc2) 
) 
+0

О, я действительно ценю это! – joshsuihn

+0

Я думал, что сокращениеByKey уже работает как (acc, x) => acc.merge (x) внутри. Не могли бы вы вкратце объяснить разницу между reduceByKey и aggregateByKey. Как правило, мы можем сказать, что aggregateByKey более эффективен (ну, я бы сказал «эффективный», если он стабильный и быстрый) Спасибо! – joshsuihn

+1

Это все о типах. 'pairs' является' RDD [(T, Double)] 'и' predorRawKey' является 'RDD [(T, StatCounter)]'. Поскольку типы не совпадают, вы не можете использовать 'reduceByKey'. Вы можете «сопоставить» пары с 'RDD [(T, StatCounter)]' и 'reduceByKey', но нет причин создавать большое количество временных объектов. – zero323

Смежные вопросы