我有一个RDD[(String, (Long, Long))]
,其中每个元素都不是唯一的:
(com.instagram.android,(2,0))
(com.android.contacts,(6,1))
(com.android.contacts,(3,4))
(com.instagram.android,(8,3))
...
所以我想获得一个RDD
,其中每个元素是每个唯一键的两个值的总和:
(com.instagram.android,(10,3))
(com.android.contacts,(9,5))
...
这是我的代码:
val appNamesAndPropertiesRdd = appNodesRdd.map({
case Row(_, appName, totalUsageTime, usageFrequency, _, _, _, _) =>
(appName, (totalUsageTime, usageFrequency))
})
答案 0 :(得分:2)
使用reduceByKey
:
val rdd = appNamesAndPropertiesRdd.reduceByKey(
(acc, elem) => (acc._1 + elem._1, acc._2 + elem._2)
)
reduceByKey
使用SCouto描述的aggregateByKey
,但具有更多可读用途。对于您的情况,aggregateByKey
的更高级功能 - 由更简单的reduceBykey
API隐藏 - 不是必需的
答案 1 :(得分:2)
首先,我认为不应该简单地添加使用频率。
现在,让我们来做你想做的事情,你想按键添加东西,你可以做到这一点
1.使用groupByKey
然后reducing
小组进行总结,
val requiredRdd = appNamesAndPropertiesRdd
.groupBy({ case (an, (tut, uf)) => an })
.map({
case (an, iter) => (
an,
iter
.map({ case (an, tut, uf) => (tut, tf) })
.reduce({ case ((tut1, tf1), (tut2, tf2)) => (tut1 + tut2, tf1 + tf2) })
)
})
或使用reduceByKey
val requiredRdd = appNamesAndPropertiesRdd
.reduceByKey({
case ((tut1, uf1), (tut2, uf2)) => (tut1 + tut2, tf1 + tf2)
})
reduceByKey
是更好的选择,有两个原因,
group
操作。groupBy
方法可能导致重新洗牌,这将是昂贵的。答案 2 :(得分:1)
函数aggregateByKey
是用于此目的的最佳函数
appNamesAndPropertiesRdd.aggregateByKey((0, 0))((acc, elem) => (acc._1 + elem._1, acc._2 +elem._2 ),(acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2))
这里解释:
aggregateByKey((0, 0))
=>这是zerovalue。最初的值。在你的情况下,因为你想要加法,如果你想要double而不是int,0,0将是初始值(0.0,0.0)
((acc, elem) => (acc._1 + elem._1, acc._2 +elem._2 )
=>第一个功能。在同一分区中累积元素。累加器将保持部分值。由于elem是一个元组,你需要将它的每一部分添加到累加器的相应部分
(acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2))
=>第二个功能。从每个分区累积累加器。
答案 3 :(得分:0)
试试这个逻辑,
rdd.groupBy(_._1).map(x=> (x._1, (x._2.map(_._2).foldLeft((0,0)) {case ((acc1, acc2),(a, b))=> (acc1+a, acc2+b)} )))