如何使用RDD API反转reduceByKey的结果?

时间:2017-05-20 11:14:34

标签: scala apache-spark rdd

我有一个(密钥,值)的RDD,我将其转换为(key,List(value1,value2,value3)的RDD,如下所示。

val rddInit = sc.parallelize(List((1, 2), (1, 3), (2, 5), (2, 7), (3, 10)))
val rddReduced = rddInit..groupByKey.mapValues(_.toList)
rddReduced.take(3).foreach(println)

这段代码给我下一个RDD: (1,列表(2,3))(2,列表(5,7))(3,列表(10))

但是现在我想从我刚刚计算出的rdd(rddReduced rdd)回到rddInit。

我的第一个猜测是在密钥和List的每个元素之间实现某种交叉产品,如下所示:

rddReduced.map{
  case (x, y) =>
    val myList:ListBuffer[(Int, Int)] = ListBuffer()
    for(element <- y) {
      myList+=new Pair(x, element)
    }
    myList.toList
}.flatMap(x => x).take(5).foreach(println)

使用此代码,我得到了初始RDD。但我不认为在Spark工作中使用ListBuffer是一种很好的做法。有没有其他方法可以解决这个问题?

4 个答案:

答案 0 :(得分:2)

使用这种操作显然不是一个好习惯。

根据我在火花峰会课程中学到的知识,你必须尽可能多地使用DataframeDataset s,使用它们你将从火花引擎的许多优化中受益

您想要做的是explode,它是通过应用explode包中的sql.functions方法预先形成的

解决方案应该是这样的:

 import spark.implicits._
 import org.apache.spark.sql.functions.explode
 import org.apache.spark.sql.functions.collect_list

 val dfInit = sc.parallelize(List((1, 2), (1, 3), (2, 5), (2, 7), (3, 10))).toDF("x", "y")
 val dfReduced = dfInit.groupBy("x").agg(collect_list("y") as "y")
 val dfResult = dfReduced.withColumn("y", explode($"y"))

dfResult将包含与dfInit

相同的数据

答案 1 :(得分:2)

我很惊讶没有人提供Scala的 for-comprehension 的解决方案(这得到了#34; desugared&#34;到flatMap和{编译时{1}}。

我不经常使用这种语法,但是当我这样做时......我发现它非常有趣。有些人更喜欢理解一系列mapflatMap,尤其是对于更复杂的转换。

map

毕竟,这就是为什么我们享受Scala的灵活性,不是吗?

答案 2 :(得分:0)

根据你的问题,我认为这就是你想做的事情

rddReduced.map{case(x, y) => y.map((x,_))}.flatMap(_).take(5).foreach(println)

您可以在分组后获得一个列表,您可以在其中再次映射它。

答案 3 :(得分:0)

以下是将分组的RDD恢复为原始格式的一种方法:

NetFramework462