如何使用自定义类聚合BYKey进行频率分配?

时间:2015-11-18 21:57:10

标签: scala apache-spark

我正在尝试创建频率分配。

我的数据采用(ColumnIndex, (Value, countOfValue))类型的(Int, (Any, Long))格式。例如,(1, (A, 10))表示列索引1,有10个A.

我的目标是获取所有索引或键的前100个值。

通过初始过滤器,我可以立即减少计算量:

val freqNumDist = numRDD.filter(x => x._2._2 > 1) 

现在我找到了一个有趣的类示例,这里似乎适合我的用例:

class TopNList (val maxSize:Int) extends Serializable {
  val topNCountsForColumnArray = new mutable.ArrayBuffer[(Any, Long)]
  var lowestColumnCountIndex:Int = -1
  var lowestValue = Long.MaxValue

  def add(newValue:Any, newCount:Long): Unit = {
    if (topNCountsForColumnArray.length < maxSize -1) {
      topNCountsForColumnArray += ((newValue, newCount))
    } else if (topNCountsForColumnArray.length == maxSize) {
      updateLowestValue
    } else {
      if (newCount > lowestValue) {
        topNCountsForColumnArray.insert(lowestColumnCountIndex, (newValue, newCount))
        updateLowestValue
      }
    }
  }

  def updateLowestValue: Unit = {
    var index = 0

    topNCountsForColumnArray.foreach{ r =>
      if (r._2 < lowestValue) {
        lowestValue = r._2
        lowestColumnCountIndex = index
      }
      index+=1
    }
  }
}

所以现在我在想的是组建一个aggregateByKey来使用这个类来获得我的前100个值!问题是我不确定如何在aggregateByKey中使用此类来实现此目标。

  val initFreq:TopNList = new TopNList(100)

  def freqSeq(u: (TopNList), v:(Double, Long)) = (
    u.add(v._1, v._2)
    )

  def freqComb(u1: TopNList, u2: TopNList) = (
    u2.topNCountsForColumnArray.foreach(r => u1.add(r._1, r._2))
    )
val freqNumDist = numRDD.filter(x => x._2._2 > 1).aggregateByKey(initFreq)(freqSeq, freqComb)

显而易见的问题是我正在使用的功能没有返回任何内容。所以我想知道如何修改这个类或者我是否需要以一种全新的眼光来考虑这个问题,只需从这个类中选择一些函数并将它们添加到我用于aggregateByKey的函数中?

我要么考虑错误的课程,要么考虑整个aggregateByKey或两者兼而有之!

1 个答案:

答案 0 :(得分:3)

您的预测实施( freqSeq freqComb )会返回单元,而您希望它们返回 TopNList

如果从根本上保持解决方案的风格,相关的impl应该是

def freqSeq(u: TopNList, v:(Any, Long)) : TopNList = {
  u.add(v._1, v._2) // operation gives void result (Unit)
  u                 // this one of TopNList type 
}

def freqComb(u1: TopNList, u2: TopNList) : TopNList = {
  u2.topNCountsForColumnArray.foreach (r => u1.add (r._1, r._2) )
  u1
}

只需查看 PairRDDFunctions aggregateByKey 签名,它对

的期望是什么
def aggregateByKey[U](zeroValue : U)(seqOp : scala.Function2[U, V, U], combOp : scala.Function2[U, U, U])(implicit evidence$3 : scala.reflect.ClassTag[U]) : org.apache.spark.rdd.RDD[scala.Tuple2[K, U]] = { /* compiled code */ }