我有一个(密钥,值)的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是一种很好的做法。有没有其他方法可以解决这个问题?
答案 0 :(得分:2)
使用这种操作显然不是一个好习惯。
根据我在火花峰会课程中学到的知识,你必须尽可能多地使用Dataframe
和Dataset
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}}。
我不经常使用这种语法,但是当我这样做时......我发现它非常有趣。有些人更喜欢理解一系列map
和flatMap
,尤其是对于更复杂的转换。
map
毕竟,这就是为什么我们享受Scala的灵活性,不是吗?
答案 2 :(得分:0)
根据你的问题,我认为这就是你想做的事情
rddReduced.map{case(x, y) => y.map((x,_))}.flatMap(_).take(5).foreach(println)
您可以在分组后获得一个列表,您可以在其中再次映射它。
答案 3 :(得分:0)
以下是将分组的RDD恢复为原始格式的一种方法:
NetFramework462