假设我有一个Tuple2
的RDD,如下所示:
<session1_w1, <0.2, 2>>,
<session1_w2, <1.3, 4>>,
<session1_w3, <0.4, 3>>,
<session2_w1, <0.5, 2>>,
<session2_w2, <2.3, 6>>
我需要将它映射到下面的RDD,这样最后一个字段是具有相同部分键值的元组的最后字段的总和,例如session1
:
2 + 4 + 3 => 9
2 + 6 => 8
所以我期望的结果是:
<session1_w1, 0.2, 9>,
<session1_w2, 1.3, 9>,
<session1_w3, 0.4, 9>,
<session2_w1, <0.5, 8>>,
<session2_w2, <2.3, 8>>
这是某种减少,但我不想丢失原来的密钥。
我可以通过映射计算求和,然后缩减到下面的RDD,但是我需要将这个RDD与第一个RDD合并以获得结果。
<session1, 9> <session2, 8>
有什么想法吗?
答案 0 :(得分:2)
您使用保留RDD结构的groupBy
(但不保留订单,因此如果您想保存订单,则必须zipWithIndex
以及之后sortBy
索引)。
否则,如果你有RDD[(String,(Double,Int))]
:
// This should give you an RDD[(Iterative(String,Double),Int)]
val group = myRDD.groupBy(_._1).map(x => (x._2.map(y => (y._1,y._2._1)),
x._2.map(y => y._2._2).reduce(_+_)))
// This will give you back your RDD of [Summed Int, String, Double] which you can then map.
val result = group.map(x => (x._2,x._1)).flatMapValues(x => x)
你也可以做一个简单的reduceByKey
(没有Double),然后将它连接回原始的RDD,这样就可以保留原来的双打。
========== EDIT ============
第二个连接解决方案只使用RDD连接。您的原始RDD格式为RDD[(String,(Double,Int))]
,我假设您已经获得了[(String,Int)]
的RDD,其中String是会话,Int是总和。连接操作只是:
RDDOriginal.join(RDDwithSum).map(x=>(x._1,x._2._1._1,x._2._2)) // This should give you the Session (String) followed by the Double and the Int (the sum).
join方法也不保留顺序,如果要保留顺序,则必须执行zipWithIndex。