【问题标题】:Spark: Not able to use accumulator on a tuple/count using scalaSpark:无法使用scala在元组/计数上使用累加器
【发布时间】:2017-06-17 23:30:20
【问题描述】:

我正在尝试用累加器逻辑替换 reduceByKey 以进行字数统计。

wc.txt

你好,你好吗

这是我目前得到的:

val words = sc.textFile("wc.txt").flatMap(_.split(" "))
val accum = sc.accumulator(0,"myacc")
for (i <- 1 to words.count.toInt) 
    foreach( x => accum+ =x)
    .....

如何处理它。任何想法或想法表示赞赏。

【问题讨论】:

  • 您的代码中的foreach 是什么?如果您想使用它,我看不出它怎么会调用RDD.foreach
  • 谢谢,实际上预期的输出是 (Hello,1), (are,2), (how,1),(you,1)
  • 我很确定这个例子不能编译。那么编译错误告诉你什么?

标签: scala apache-spark rdd


【解决方案1】:

确实,为此使用累加器很麻烦且不推荐 - 但为了完整起见 - 以下是它的完成方式(至少对于 Spark 版本 1.6 )。请注意,这使用了一个已弃用的 API,该 API 不会成为下一个版本的一部分。

您需要一个Map[String, Long] 累加器,默认情况下不可用,因此您需要创建自己的AccumulableParam 实现并隐式使用它:

// some data:
val words = sc.parallelize(Seq("Hello how are are you")).flatMap(_.split(" "))

// aliasing the type, just for convenience
type AggMap = Map[String, Long]

// creating an implicit AccumulableParam that counts by String key
implicit val param: AccumulableParam[AggMap, String] = new AccumulableParam[AggMap, String] {
  // increase matching value by 1, or create it if missing
  override def addAccumulator(r: AggMap, t: String): AggMap = 
    r.updated(t, r.getOrElse(t, 0L) + 1L)

  // merge two maps by summing matching values 
  override def addInPlace(r1: AggMap, r2: AggMap): AggMap = 
    r1 ++ r2.map { case (k, v) => k -> (v + r1.getOrElse(k, 0L)) }

  // start with an empty map
  override def zero(initialValue: AggMap): AggMap = Map.empty
}

// create the accumulator; This will use the above `param` implicitly
val acc = sc.accumulable[AggMap, String](Map.empty[String, Long])

// add each word to accumulator; the `count()` can be replaced by any Spark action - 
// we just need to trigger the calculation of the mapped RDD 
words.map(w => { acc.add(w); w }).count()

// after the action, we acn read the value of the accumulator
val result: AggMap = acc.value

result.foreach(println)
// (Hello,1)
// (how,1)
// (are,2)
// (you,1)

【讨论】:

    【解决方案2】:

    据我了解,您想使用 Spark 累加器计算文本文件中的所有单词,在这种情况下,您可以使用:

    words.foreach(_ => accum.add(1L))
    

    【讨论】:

    • 谢谢。但最终的输出应该是 (Hello,1), (are,2), (how,1),(you,1)
    • 在这种情况下使用累加器不是一个好主意......我可以提出的唯一使用累加器的解决方案是为每个不同的单词创建专用的累加器,并在 foreach 操作中增加相关的累加器。明显的缺点是您需要预先知道不同单词的列表......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 2022-08-03
    • 2018-07-14
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    相关资源
    最近更新 更多