在Apache Spark(Scala)中使用reduceByKey

时间:2014-06-05 22:58:08

标签: scala apache-spark

我有一个类型的元组列表:(用户ID,名称,计数)。

例如,

val x = sc.parallelize(List(
    ("a", "b", 1),
    ("a", "b", 1),
    ("c", "b", 1),
    ("a", "d", 1))
)

我正在尝试将此集合缩减为每种类型的类型 元素名称被计算在内。

所以在上面val x被转换为:

(a,ArrayBuffer((d,1), (b,2)))
(c,ArrayBuffer((b,1)))

以下是我目前使用的代码:

val byKey = x.map({case (id,uri,count) => (id,uri)->count})

val grouped = byKey.groupByKey
val count = grouped.map{case ((id,uri),count) => ((id),(uri,count.sum))}
val grouped2: org.apache.spark.rdd.RDD[(String, Seq[(String, Int)])] = count.groupByKey

grouped2.foreach(println)

我正在尝试使用reduceByKey,因为它的执行速度比groupByKey快。

如何实现reduceByKey而不是上面提供的代码 相同的映射?

3 个答案:

答案 0 :(得分:26)

关注您的代码:

val byKey = x.map({case (id,uri,count) => (id,uri)->count})

你可以这样做:

val reducedByKey = byKey.reduceByKey(_ + _)

scala> reducedByKey.collect.foreach(println)
((a,d),1)
((a,b),2)
((c,b),1)

PairRDDFunctions[K,V].reduceByKey采用关联reduce函数,该函数可应用于RDD [(K,V)]的V型。换句话说,您需要一个函数f[V](e1:V, e2:V) : V。在这个特殊情况下,对Ints求和:(x:Int, y:Int) => x+y_ + _以简短的下划线表示法。

对于记录:reduceByKey的性能优于groupByKey,因为它尝试在shuffle / reduce阶段之前在本地应用reduce函数。在分组之前,groupByKey会强制对所有元素进行随机播放。

答案 1 :(得分:5)

您的原始数据结构是:RDD [(String,String,Int)]和reduceByKey只能在数据结构为RDD [(K,V)]时使用。

val kv = x.map(e => e._1 -> e._2 -> e._3) // kv is RDD[((String, String), Int)]
val reduced = kv.reduceByKey(_ + _)       // reduced is RDD[((String, String), Int)]
val kv2 = reduced.map(e => e._1._1 -> (e._1._2 -> e._2)) // kv2 is RDD[(String, (String, Int))]
val grouped = kv2.groupByKey()            // grouped is RDD[(String, Iterable[(String, Int)])]
grouped.foreach(println)

答案 2 :(得分:0)

语法如下:

reduceByKey(func: Function2[V, V, V]): JavaPairRDD[K, V],

表示对于RDD中的相同键,它采用值(肯定是相同类型)执行作为函数的一部分提供的操作,并返回与父RDD相同类型的值。