Scala Apache Spark RDD中每个唯一键的和值
我有一个Scala Apache Spark RDD中每个唯一键的和值,scala,apache-spark,Scala,Apache Spark,我有一个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.contac
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))
})
使用
reduceByKey
:
val rdd = appNamesAndPropertiesRdd.reduceByKey(
(acc, elem) => (acc._1 + elem._1, acc._2 + elem._2)
)
reduceByKey
使用SCouto描述的aggregateByKey
,但具有更具可读性的用法。就您的情况而言,aggregateByKey
的更高级功能(由reduceebykey
的更简单API隐藏)是不必要的函数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))
=>这是零值。将作为初始值的值。在本例中,由于需要加法,如果希望使用double而不是int,那么0,0将是初始值(0.0,0.0)
((acc,elem)=>(acc.\u 1+elem.\u 1,acc.\u 2+elem.\u 2)
=>第一个函数。要在同一分区中累加元素,累加器将保存部分值。由于elem是一个元组,您需要将它的每个部分添加到累加器的相应部分
(acc1,acc2)=>(acc1.\u 1+acc2.\u 1,acc1.\u 2+acc2.\u 2))
=>第二个函数。从每个分区累积累加器 试试这个逻辑
rdd.groupBy(_._1).map(x=> (x._1, (x._2.map(_._2).foldLeft((0,0)) {case ((acc1, acc2),(a, b))=> (acc1+a, acc2+b)} )))
首先,我不认为usageFrequency应该简单地相加 现在,让我们来看看你想做什么,你想按键添加东西,你可以做到 1.使用
groupByKey
然后reduce
对组进行总结
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
是一个更好的选择,原因有二:
组
操作groupBy
方法可能导致成本高昂的重组它将比reduceByKey
慢。groupBy({case(an,tut,uf)=>an})
不正常,OP有。groupBy({case(an,(tut,uf))=>an})
@Fobi Acc表示累加器;)可能您指的是元组中第一个元素中的max。然后appnamesandpropertiesdd.reduceByKey((acc,elem)=>Math.max(acc,elem.\u 1))
这里acc只是一个长元组,不是元组,但我们仍然减少元组,这就是为什么我调用。\u 1
的原因elem@TGaweda如果我尝试,我会出现一个错误:重载方法值max和可选项:(x$1:Double,x$2:Double)Double(x$1:Float,x$2:Float)Float(x$1:Long,x$2:Long)Long(x$1:Int,x$2:Int)Int不能应用于((Long,Long),Long)@Fobi奇怪。请尝试appNamesAndPropertiesRdd.reduceByKey((acc,elem)=>(Math.max(acc.u.1,elem.u.1),Math.max(acc.u.2,elem.u.2)).map(x=>(x.u.1,x.u.2.\u.u.I)
@TGaweda我拥有:值映射不是(Int,Int)的成员可能原因:可能在“值映射”之前缺少分号?@Fobi在之前加上额外的。
-type错误;)